diff --git a/CMakeLists.txt b/CMakeLists.txt index a2b31d174..289cecad8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ option(GUI "Build GUI components (AlethZero, Mix)" ON) option(TESTS "Build the tests." ON) option(EVMJIT "Build just-in-time compiler for EVM code (requires LLVM)" OFF) option(ETHASHCL "Build in support for GPU mining via OpenCL" OFF) +option(JSCONSOLE "Build in javascript console" OFF) # propagates CMake configuration options to the compiler function(configureProject) @@ -154,7 +155,7 @@ set (ETH_HAVE_WEBENGINE 1) # Backwards compatibility if (HEADLESS) message("*** WARNING: -DHEADLESS=1 option is DEPRECATED! Use -DBUNDLE=minimal or -DGUI=0") - set(BUNDLE "minimal") + set(GUI OFF) endif () # TODO: Abstract into something sensible and move into a function. @@ -193,9 +194,14 @@ eth_format_option(GUI) eth_format_option(TESTS) eth_format_option(TOOLS) eth_format_option(ETHASHCL) +eth_format_option(JSCONSOLE) eth_format_option_on_decent_platform(SERPENT) eth_format_option_on_decent_platform(NCURSES) +if (JSCONSOLE) + set(JSONRPC ON) +endif() + if (GUI) set(JSONRPC ON) endif() @@ -284,6 +290,7 @@ message("-- GUI Build GUI components ${GUI}") message("-- NCURSES Build NCurses components ${NCURSES}") message("-- TESTS Build tests ${TESTS}") message("-- ETHASHCL Build OpenCL components (experimental!) ${ETHASHCL}") +message("-- JSCONSOLE Build with javascript console ${JSCONSOLE}") message("-- EVMJIT Build LLVM-based JIT EVM (experimental!) ${EVMJIT}") message("------------------------------------------------------------------------") message("") @@ -328,6 +335,11 @@ if (JSONRPC) add_subdirectory(libweb3jsonrpc) endif() +if (JSCONSOLE) + add_subdirectory(libjsengine) + add_subdirectory(libjsconsole) +endif() + add_subdirectory(secp256k1) add_subdirectory(libp2p) add_subdirectory(libdevcrypto) @@ -384,7 +396,22 @@ if (GUI) endif() -#unset(TARGET_PLATFORM CACHE) +if (APPLE AND GUI) + + add_custom_target(appdmg + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND ${CMAKE_COMMAND} + -DAPP_DMG_EXE=${ETH_APP_DMG} + -DAPP_DMG_FILE=appdmg.json.in + -DAPP_DMG_ICON="alethzero/alethzero.icns" + -DAPP_DMG_BACKGROUND="bg.png" + -DETH_BUILD_DIR="${CMAKE_BINARY_DIR}" + -DETH_MIX_APP="$" + -DETH_ALETHZERO_APP="$" + -P "${ETH_SCRIPTS_DIR}/appdmg.cmake" + ) + +endif () if (WIN32) # packaging stuff diff --git a/alethzero/Context.h b/alethzero/Context.h index 20c9696f9..4a52366db 100644 --- a/alethzero/Context.h +++ b/alethzero/Context.h @@ -29,7 +29,7 @@ class QComboBox; -namespace dev { namespace eth { struct StateDiff; } } +namespace dev { namespace eth { struct StateDiff; class KeyManager; } } #define Small "font-size: small; " #define Mono "font-family: Ubuntu Mono, Monospace, Lucida Console, Courier New; font-weight: bold; " @@ -64,5 +64,8 @@ public: virtual std::pair fromString(std::string const& _a) const = 0; virtual std::string renderDiff(dev::eth::StateDiff const& _d) const = 0; virtual std::string render(dev::Address const& _a) const = 0; + virtual dev::Secret retrieveSecret(dev::Address const& _a) const = 0; + virtual dev::eth::KeyManager& keyManager() = 0; + }; diff --git a/alethzero/Debugger.h b/alethzero/Debugger.h index 76ef6a0d3..38ed973df 100644 --- a/alethzero/Debugger.h +++ b/alethzero/Debugger.h @@ -45,7 +45,7 @@ struct WorldState dev::u256s stack; dev::bytes memory; dev::bigint gasCost; - std::map storage; + std::unordered_map storage; std::vector levels; }; diff --git a/alethzero/ExportState.cpp b/alethzero/ExportState.cpp index a8e47ad6a..c11132768 100644 --- a/alethzero/ExportState.cpp +++ b/alethzero/ExportState.cpp @@ -91,7 +91,7 @@ void ExportStateDialog::fillBlocks() while (i > 0 && i >= m_recentBlocks) ui->block->removeItem(i--); - h256Set blocks; + h256Hash blocks; for (QString f: filters) { if (f.startsWith("#")) @@ -153,13 +153,17 @@ void ExportStateDialog::generateJSON() auto address = Address((byte const*)hba.data(), Address::ConstructFromPointer); json << prefix << "\t\"" << toHex(address.ref()) << "\":\n\t{\n\t\t\"wei\": \"" << ethereum()->balanceAt(address, m_block) << "\",\n"; json << "\t\t\"code\": \"" << toHex(ethereum()->codeAt(address, m_block)) << "\",\n"; - std::map storage = ethereum()->storageAt(address, m_block); + std::unordered_map storage = ethereum()->storageAt(address, m_block); if (!storage.empty()) { json << "\t\t\"storage\":\n\t\t{\n"; + std::string storagePrefix; for (auto s: storage) - json << "\t\t\t\"" << toHex(s.first) << "\": \"" << toHex(s.second) << "\"" << (s.first == storage.rbegin()->first ? "" : ",") <<"\n"; - json << "\t\t}\n"; + { + json << storagePrefix << "\t\t\t\"" << toHex(s.first) << "\": \"" << toHex(s.second) << "\""; + storagePrefix = ",\n"; + } + json << "\n\t\t}\n"; } json << "\t}"; prefix = ",\n"; diff --git a/alethzero/Main.ui b/alethzero/Main.ui index 736af8684..5b0ad7582 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -548,12 +548,15 @@ QFrame::NoFrame - - QAbstractItemView::InternalMove + + false true + + true + diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index e5504cab2..87c9c2dc9 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -143,6 +144,38 @@ Main::Main(QWidget *parent) : // ui->log->addItem(QString::fromStdString(s)); }; + // Open Key Store + bool opened = false; + if (m_keyManager.exists()) + while (!opened) + { + QString s = QInputDialog::getText(nullptr, "Master password", "Enter your MASTER account password.", QLineEdit::Password, QString()); + if (m_keyManager.load(s.toStdString())) + opened = true; + else if (QMessageBox::question( + nullptr, + "Invalid password entered", + "The password you entered is incorrect. If you have forgotten your password, and you wish to start afresh, manually remove the file: " + QString::fromStdString(getDataDir("ethereum")) + "/keys.info", + QMessageBox::Retry, + QMessageBox::Abort) + == QMessageBox::Abort) + exit(0); + } + if (!opened) + { + QString password; + while (true) + { + password = QInputDialog::getText(nullptr, "Master password", "Enter a MASTER password for your key store. Make it strong. You probably want to write it down somewhere and keep it safe and secure; your identity will rely on this - you never want to lose it.", QLineEdit::Password, QString()); + QString confirm = QInputDialog::getText(nullptr, "Master password", "Confirm this password by typing it again", QLineEdit::Password, QString()); + if (password == confirm) + break; + QMessageBox::warning(nullptr, "Try again", "You entered two different passwords - please enter the same password twice.", QMessageBox::Ok); + } + m_keyManager.create(password.toStdString()); + m_keyManager.import(Secret::random(), "Default identity"); + } + #if ETH_DEBUG m_servers.append("127.0.0.1:30300"); #endif @@ -168,15 +201,13 @@ Main::Main(QWidget *parent) : ui->blockCount->setText(QString("PV%1.%2 D%3 %4-%5 v%6").arg(eth::c_protocolVersion).arg(eth::c_minorProtocolVersion).arg(c_databaseVersion).arg(QString::fromStdString(ProofOfWork::name())).arg(ProofOfWork::revision()).arg(dev::Version)); - connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved())); - QSettings s("ethereum", "alethzero"); m_networkConfig = s.value("peers").toByteArray(); bytesConstRef network((byte*)m_networkConfig.data(), m_networkConfig.size()); m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir(), WithExisting::Trust, {"eth", "shh"}, p2p::NetworkPreferences(), network)); m_httpConnector.reset(new jsonrpc::HttpServer(SensibleHttpPort, "", "", dev::SensibleHttpThreads)); - m_server.reset(new OurWebThreeStubServer(*m_httpConnector, *web3(), keysAsVector(m_myKeys), this)); + m_server.reset(new OurWebThreeStubServer(*m_httpConnector, *web3(), this)); connect(&*m_server, SIGNAL(onNewId(QString)), SLOT(addNewId(QString))); m_server->setIdentities(keysAsVector(owned())); m_server->StartListening(); @@ -198,6 +229,7 @@ Main::Main(QWidget *parent) : // ui->webView->page()->settings()->setAttribute(QWebEngineSettings::DeveloperExtrasEnabled, true); // QWebEngineInspector* inspector = new QWebEngineInspector(); // inspector->setPage(page); + setBeneficiary(*m_keyManager.accounts().begin()); readSettings(); #if !ETH_FATDB removeDockWidget(ui->dockWidget_accounts); @@ -358,9 +390,9 @@ void Main::installBalancesWatch() // TODO: Update for new currencies reg. for (unsigned i = 0; i < ethereum()->stateAt(coinsAddr, PendingBlock); ++i) altCoins.push_back(right160(ethereum()->stateAt(coinsAddr, i + 1))); - for (auto i: m_myKeys) + for (auto const& i: m_keyManager.accounts()) for (auto c: altCoins) - tf.address(c).topic(0, h256(i.address(), h256::AlignRight)); + tf.address(c).topic(0, h256(i, h256::AlignRight)); uninstallWatch(m_balancesFilter); m_balancesFilter = installWatch(tf, [=](LocalisedLogEntries const&){ onBalancesChange(); }); @@ -429,7 +461,7 @@ void Main::load(QString _s) void Main::on_newTransaction_triggered() { - m_transact.setEnvironment(m_myKeys, ethereum(), &m_natSpecDB); + m_transact.setEnvironment(m_keyManager.accounts(), ethereum(), &m_natSpecDB); m_transact.exec(); } @@ -616,17 +648,7 @@ void Main::on_paranoia_triggered() void Main::writeSettings() { QSettings s("ethereum", "alethzero"); - { - QByteArray b; - b.resize(sizeof(Secret) * m_myKeys.size()); - auto p = b.data(); - for (auto i: m_myKeys) - { - memcpy(p, &(i.secret()), sizeof(Secret)); - p += sizeof(Secret); - } - s.setValue("address", b); - } + s.remove("address"); { QByteArray b; b.resize(sizeof(Secret) * m_myIdentities.size()); @@ -666,6 +688,20 @@ void Main::writeSettings() s.setValue("windowState", saveState()); } +Secret Main::retrieveSecret(Address const& _a) const +{ + auto info = m_keyManager.accountDetails()[_a]; + while (true) + { + if (Secret s = m_keyManager.secret(_a, [&](){ + return QInputDialog::getText(const_cast(this), "Import Account Key", QString("Enter the password for the account %2 (%1). The hint is:\n%3").arg(QString::fromStdString(_a.abridged())).arg(QString::fromStdString(info.first)).arg(QString::fromStdString(info.second)), QLineEdit::Password).toStdString(); + })) + return s; + else if (QMessageBox::warning(const_cast(this), "Incorrect Password", "The password you gave is incorrect for this key.", QMessageBox::Retry, QMessageBox::Cancel) == QMessageBox::Cancel) + return Secret(); + } +} + void Main::readSettings(bool _skipGeometry) { QSettings s("ethereum", "alethzero"); @@ -675,22 +711,17 @@ void Main::readSettings(bool _skipGeometry) restoreState(s.value("windowState").toByteArray()); { - m_myKeys.clear(); QByteArray b = s.value("address").toByteArray(); - if (b.isEmpty()) - m_myKeys.append(KeyPair::create()); - else + if (!b.isEmpty()) { h256 k; for (unsigned i = 0; i < b.size() / sizeof(Secret); ++i) { memcpy(&k, b.data() + i * sizeof(Secret), sizeof(Secret)); - if (!count(m_myKeys.begin(), m_myKeys.end(), KeyPair(k))) - m_myKeys.append(KeyPair(k)); + if (!m_keyManager.accounts().count(KeyPair(k).address())) + m_keyManager.import(k, "Imported (UNSAFE) key."); } } - ethereum()->setAddress(m_myKeys.back().address()); - m_server->setAccounts(keysAsVector(m_myKeys)); } { @@ -735,16 +766,38 @@ void Main::readSettings(bool _skipGeometry) on_urlEdit_returnPressed(); } +std::string Main::getPassword(std::string const& _title, std::string const& _for) +{ + QString password; + while (true) + { + password = QInputDialog::getText(nullptr, QString::fromStdString(_title), QString::fromStdString(_for), QLineEdit::Password, QString()); + QString confirm = QInputDialog::getText(nullptr, QString::fromStdString(_title), "Confirm this password by typing it again", QLineEdit::Password, QString()); + if (password == confirm) + break; + QMessageBox::warning(nullptr, QString::fromStdString(_title), "You entered two different passwords - please enter the same password twice.", QMessageBox::Ok); + } + return password.toStdString(); +} + void Main::on_importKey_triggered() { - QString s = QInputDialog::getText(this, "Import Account Key", "Enter account's secret key"); + QString s = QInputDialog::getText(this, "Import Account Key", "Enter account's secret key", QLineEdit::Password); bytes b = fromHex(s.toStdString()); if (b.size() == 32) { auto k = KeyPair(h256(b)); - if (std::find(m_myKeys.begin(), m_myKeys.end(), k) == m_myKeys.end()) + if (!m_keyManager.accounts().count(k.address())) { - m_myKeys.append(k); + QString s = QInputDialog::getText(this, "Import Account Key", "Enter this account's name"); + if (QMessageBox::question(this, "Additional Security?", "Would you like to use additional security for this key? This lets you protect it with a different password to other keys, but also means you must re-enter the key's password every time you wish to use the account.", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) + { + std::string password = getPassword("Import Account Key", "Enter the password you would like to use for this key. Don't forget it!"); + std::string hint = QInputDialog::getText(this, "Import Account Key", "Enter a hint to help you remember this password.").toStdString(); + m_keyManager.import(k.secret(), s.toStdString(), password, hint); + } + else + m_keyManager.import(k.secret(), s.toStdString()); keysChanged(); } else @@ -785,15 +838,8 @@ void Main::on_importKeyFile_triggered() } cnote << k.address(); - if (std::find(m_myKeys.begin(), m_myKeys.end(), k) == m_myKeys.end()) - { - if (m_myKeys.empty()) - { - m_myKeys.push_back(KeyPair::create()); - keysChanged(); - } - ethereum()->submitTransaction(k.sec(), ethereum()->balanceAt(k.address()) - gasPrice() * c_txGas, m_myKeys.back().address(), {}, c_txGas, gasPrice()); - } + if (!m_keyManager.accounts().count(k.address())) + ethereum()->submitTransaction(k.sec(), ethereum()->balanceAt(k.address()) - gasPrice() * c_txGas, m_beneficiary, {}, c_txGas, gasPrice()); else QMessageBox::warning(this, "Already Have Key", "Could not import the secret key: we already own this account."); } @@ -812,10 +858,12 @@ void Main::on_importKeyFile_triggered() void Main::on_exportKey_triggered() { - if (ui->ourAccounts->currentRow() >= 0 && ui->ourAccounts->currentRow() < m_myKeys.size()) + if (ui->ourAccounts->currentRow() >= 0) { - auto k = m_myKeys[ui->ourAccounts->currentRow()]; - QMessageBox::information(this, "Export Account Key", "Secret key to account " + QString::fromStdString(render(k.address()) + " is:\n" + toHex(k.sec().ref()))); + auto hba = ui->ourAccounts->currentItem()->data(Qt::UserRole).toByteArray(); + Address h((byte const*)hba.data(), Address::ConstructFromPointer); + Secret s = retrieveSecret(h); + QMessageBox::information(this, "Export Account Key", "Secret key to account " + QString::fromStdString(render(h) + " is:\n" + s.hex())); } } @@ -913,6 +961,24 @@ void Main::refreshMining() */ } +void Main::setBeneficiary(Address const& _b) +{ + for (int i = 0; i < ui->ourAccounts->count(); ++i) + { + auto hba = ui->ourAccounts->item(i)->data(Qt::UserRole).toByteArray(); + auto h = Address((byte const*)hba.data(), Address::ConstructFromPointer); + ui->ourAccounts->item(i)->setCheckState(h == _b ? Qt::Checked : Qt::Unchecked); + } + m_beneficiary = _b; + ethereum()->setAddress(_b); +} + +void Main::on_ourAccounts_itemClicked(QListWidgetItem* _i) +{ + auto hba = _i->data(Qt::UserRole).toByteArray(); + setBeneficiary(Address((byte const*)hba.data(), Address::ConstructFromPointer)); +} + void Main::refreshBalances() { cwatch << "refreshBalances()"; @@ -931,11 +997,13 @@ void Main::refreshBalances() // cdebug << n << addr << denom << sha3(h256(n).asBytes()); altCoins[addr] = make_tuple(fromRaw(n), 0, denom); }*/ - for (auto i: m_myKeys) + for (pair> const& i: m_keyManager.accountDetails()) { - u256 b = ethereum()->balanceAt(i.address()); - (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(b).c_str()).arg(QString::fromStdString(render(i.address()))).arg((unsigned)ethereum()->countAt(i.address())), ui->ourAccounts)) - ->setData(Qt::UserRole, QByteArray((char const*)i.address().data(), Address::size)); + u256 b = ethereum()->balanceAt(i.first); + QListWidgetItem* li = new QListWidgetItem(QString("%4 %2: %1 [%3]").arg(formatBalance(b).c_str()).arg(QString::fromStdString(render(i.first))).arg((unsigned)ethereum()->countAt(i.first)).arg(QString::fromStdString(i.second.first)), ui->ourAccounts); + li->setData(Qt::UserRole, QByteArray((char const*)i.first.data(), Address::size)); + li->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + li->setCheckState(m_beneficiary == i.first ? Qt::Checked : Qt::Unchecked); totalBalance += b; // for (auto& c: altCoins) @@ -1092,7 +1160,7 @@ void Main::refreshBlockChain() auto const& bc = ethereum()->blockChain(); QStringList filters = ui->blockChainFilter->text().toLower().split(QRegExp("\\s+"), QString::SkipEmptyParts); - h256Set blocks; + h256Hash blocks; for (QString f: filters) if (f.size() == 64) { @@ -1385,23 +1453,6 @@ void Main::on_transactionQueue_currentItemChanged() ui->pendingInfo->moveCursor(QTextCursor::Start); } -void Main::ourAccountsRowsMoved() -{ - QList myKeys; - for (int i = 0; i < ui->ourAccounts->count(); ++i) - { - auto hba = ui->ourAccounts->item(i)->data(Qt::UserRole).toByteArray(); - auto h = Address((byte const*)hba.data(), Address::ConstructFromPointer); - for (auto i: m_myKeys) - if (i.address() == h) - myKeys.push_back(i); - } - m_myKeys = myKeys; - - if (m_server.get()) - m_server->setAccounts(keysAsVector(m_myKeys)); -} - void Main::on_inject_triggered() { QString s = QInputDialog::getText(this, "Inject Transaction", "Enter transaction dump in hex"); @@ -1827,7 +1878,7 @@ void Main::on_mine_triggered() { if (ui->mine->isChecked()) { - ethereum()->setAddress(m_myKeys.last().address()); + ethereum()->setAddress(m_beneficiary); ethereum()->startMining(); } else @@ -1837,7 +1888,6 @@ void Main::on_mine_triggered() void Main::keysChanged() { onBalancesChange(); - m_server->setAccounts(keysAsVector(m_myKeys)); } bool beginsWith(Address _a, bytes const& _b) @@ -1901,24 +1951,39 @@ void Main::on_newAccount_triggered() t->join(); delete t; } - m_myKeys.append(p); + + QString s = QInputDialog::getText(this, "Create Account", "Enter this account's name"); + if (QMessageBox::question(this, "Create Account", "Would you like to use additional security for this key? This lets you protect it with a different password to other keys, but also means you must re-enter the key's password every time you wish to use the account.", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) + { + std::string password = getPassword("Create Account", "Enter the password you would like to use for this key. Don't forget it!"); + std::string hint = QInputDialog::getText(this, "Create Account", "Enter a hint to help you remember this password.").toStdString(); + m_keyManager.import(p.secret(), s.toStdString(), password, hint); + } + else + m_keyManager.import(p.secret(), s.toStdString()); keysChanged(); } void Main::on_killAccount_triggered() { - if (ui->ourAccounts->currentRow() >= 0 && ui->ourAccounts->currentRow() < m_myKeys.size()) + if (ui->ourAccounts->currentRow() >= 0) { - auto k = m_myKeys[ui->ourAccounts->currentRow()]; + auto hba = ui->accounts->currentItem()->data(Qt::UserRole).toByteArray(); + Address h((byte const*)hba.data(), Address::ConstructFromPointer); + auto k = m_keyManager.accountDetails()[h]; if ( - ethereum()->balanceAt(k.address()) != 0 && - QMessageBox::critical(this, "Kill Account?!", - QString::fromStdString("Account " + render(k.address()) + " has " + formatBalance(ethereum()->balanceAt(k.address())) + " in it. It, and any contract that this account can access, will be lost forever if you continue. Do NOT continue unless you know what you are doing.\n" + ethereum()->balanceAt(h) != 0 && + QMessageBox::critical(this, QString::fromStdString("Kill Account " + k.first + "?!"), + QString::fromStdString("Account " + k.first + " (" + render(h) + ") has " + formatBalance(ethereum()->balanceAt(h)) + " in it. It, and any contract that this account can access, will be lost forever if you continue. Do NOT continue unless you know what you are doing.\n" "Are you sure you want to continue?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) return; - m_myKeys.erase(m_myKeys.begin() + ui->ourAccounts->currentRow()); + m_keyManager.kill(h); + if (m_keyManager.accounts().empty()) + m_keyManager.import(Secret::random(), "Default account"); keysChanged(); + if (m_beneficiary == h) + setBeneficiary(*m_keyManager.accounts().begin()); } } @@ -1929,7 +1994,8 @@ void Main::on_go_triggered() ui->net->setChecked(true); on_net_triggered(); } - web3()->addNode(p2p::NodeId(), Host::pocHost()); + for (auto const& i: Host::pocHosts()) + web3()->requirePeer(i.first, i.second); } std::string Main::prettyU256(dev::u256 const& _n) const diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 127b174c6..51d4cc8f4 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include "Context.h" @@ -42,6 +43,8 @@ #include "NatspecHandler.h" #include "Connect.h" +class QListWidgetItem; + namespace Ui { class Main; } @@ -86,10 +89,14 @@ public: std::pair fromString(std::string const& _a) const override; std::string renderDiff(dev::eth::StateDiff const& _d) const override; - QList owned() const { return m_myIdentities + m_myKeys; } + QList owned() const { return m_myIdentities; } dev::u256 gasPrice() const { return 10 * dev::eth::szabo; } + dev::eth::KeyManager& keyManager() override { return m_keyManager; } + + dev::Secret retrieveSecret(dev::Address const& _a) const override; + public slots: void load(QString _file); void note(QString _entry); @@ -144,7 +151,7 @@ private slots: void on_exportState_triggered(); // Stuff concerning the blocks/transactions/accounts panels - void ourAccountsRowsMoved(); + void on_ourAccounts_itemClicked(QListWidgetItem* _i); void on_ourAccounts_doubleClicked(); void on_accounts_doubleClicked(); void on_accounts_currentItemChanged(); @@ -236,6 +243,9 @@ private: void refreshBlockCount(); void refreshBalances(); + void setBeneficiary(dev::Address const& _b); + std::string getPassword(std::string const& _title, std::string const& _for); + std::unique_ptr ui; std::unique_ptr m_webThree; @@ -247,10 +257,11 @@ private: QByteArray m_networkConfig; QStringList m_servers; - QList m_myKeys; QList m_myIdentities; + dev::eth::KeyManager m_keyManager; QString m_privateChain; dev::Address m_nameReg; + dev::Address m_beneficiary; QList> m_consoleHistory; QMutex m_logLock; diff --git a/alethzero/OurWebThreeStubServer.cpp b/alethzero/OurWebThreeStubServer.cpp index 161bb4926..d3ee4f41b 100644 --- a/alethzero/OurWebThreeStubServer.cpp +++ b/alethzero/OurWebThreeStubServer.cpp @@ -20,23 +20,23 @@ */ #include "OurWebThreeStubServer.h" - #include #include #include #include - #include "MainWin.h" - using namespace std; using namespace dev; using namespace dev::eth; -OurWebThreeStubServer::OurWebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, WebThreeDirect& _web3, - vector const& _accounts, Main* _main): - WebThreeStubServer(_conn, _web3, _accounts), m_web3(&_web3), m_main(_main) +OurWebThreeStubServer::OurWebThreeStubServer( + jsonrpc::AbstractServerConnector& _conn, + WebThreeDirect& _web3, + Main* _main +): + WebThreeStubServer(_conn, _web3, make_shared(_web3, _main), _main->owned().toVector().toStdVector()), + m_main(_main) { - connect(_main, SIGNAL(poll()), this, SLOT(doValidations())); } string OurWebThreeStubServer::shh_newIdentity() @@ -46,7 +46,18 @@ string OurWebThreeStubServer::shh_newIdentity() return toJS(kp.pub()); } -bool OurWebThreeStubServer::showAuthenticationPopup(string const& _title, string const& _text) +OurAccountHolder::OurAccountHolder( + WebThreeDirect& _web3, + Main* _main +): + AccountHolder([=](){ return m_web3->ethereum(); }), + m_web3(&_web3), + m_main(_main) +{ + connect(_main, SIGNAL(poll()), this, SLOT(doValidations())); +} + +bool OurAccountHolder::showAuthenticationPopup(string const& _title, string const& _text) { if (!m_main->confirm()) { @@ -66,18 +77,18 @@ bool OurWebThreeStubServer::showAuthenticationPopup(string const& _title, string //return button == QMessageBox::Ok; } -bool OurWebThreeStubServer::showCreationNotice(TransactionSkeleton const& _t, bool _toProxy) +bool OurAccountHolder::showCreationNotice(TransactionSkeleton const& _t, bool _toProxy) { return showAuthenticationPopup("Contract Creation Transaction", string("ÐApp is attemping to create a contract; ") + (_toProxy ? "(this transaction is not executed directly, but forwarded to another ÐApp) " : "") + "to be endowed with " + formatBalance(_t.value) + ", with additional network fees of up to " + formatBalance(_t.gas * _t.gasPrice) + ".\n\nMaximum total cost is " + formatBalance(_t.value + _t.gas * _t.gasPrice) + "."); } -bool OurWebThreeStubServer::showSendNotice(TransactionSkeleton const& _t, bool _toProxy) +bool OurAccountHolder::showSendNotice(TransactionSkeleton const& _t, bool _toProxy) { return showAuthenticationPopup("Fund Transfer Transaction", "ÐApp is attempting to send " + formatBalance(_t.value) + " to a recipient " + m_main->pretty(_t.to) + (_toProxy ? " (this transaction is not executed directly, but forwarded to another ÐApp)" : "") + ", with additional network fees of up to " + formatBalance(_t.gas * _t.gasPrice) + ".\n\nMaximum total cost is " + formatBalance(_t.value + _t.gas * _t.gasPrice) + "."); } -bool OurWebThreeStubServer::showUnknownCallNotice(TransactionSkeleton const& _t, bool _toProxy) +bool OurAccountHolder::showUnknownCallNotice(TransactionSkeleton const& _t, bool _toProxy) { return showAuthenticationPopup("DANGEROUS! Unknown Contract Transaction!", "ÐApp is attempting to call into an unknown contract at address " + @@ -93,25 +104,47 @@ bool OurWebThreeStubServer::showUnknownCallNotice(TransactionSkeleton const& _t, "REJECT UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!"); } -void OurWebThreeStubServer::authenticate(TransactionSkeleton const& _t, bool _toProxy) +void OurAccountHolder::authenticate(TransactionSkeleton const& _t) { Guard l(x_queued); - m_queued.push(make_pair(_t, _toProxy)); + m_queued.push(_t); } -void OurWebThreeStubServer::doValidations() +void OurAccountHolder::doValidations() { Guard l(x_queued); while (!m_queued.empty()) { - auto q = m_queued.front(); + auto t = m_queued.front(); m_queued.pop(); - if (validateTransaction(q.first, q.second)) - WebThreeStubServerBase::authenticate(q.first, q.second); + + bool proxy = isProxyAccount(t.from); + if (!proxy && !isRealAccount(t.from)) + { + cwarn << "Trying to send from non-existant account" << t.from; + return; + } + + // TODO: determine gas price. + + if (!validateTransaction(t, proxy)) + return; + + if (proxy) + queueTransaction(t); + else + // sign and submit. + if (Secret s = m_main->retrieveSecret(t.from)) + m_web3->ethereum()->submitTransaction(s, t); } } -bool OurWebThreeStubServer::validateTransaction(TransactionSkeleton const& _t, bool _toProxy) +AddressHash OurAccountHolder::realAccounts() const +{ + return m_main->keyManager().accounts(); +} + +bool OurAccountHolder::validateTransaction(TransactionSkeleton const& _t, bool _toProxy) { if (_t.creation) { diff --git a/alethzero/OurWebThreeStubServer.h b/alethzero/OurWebThreeStubServer.h index 95cf70438..a07188b2d 100644 --- a/alethzero/OurWebThreeStubServer.h +++ b/alethzero/OurWebThreeStubServer.h @@ -25,26 +25,29 @@ #include #include #include +#include class Main; -class OurWebThreeStubServer: public QObject, public WebThreeStubServer +class OurAccountHolder: public QObject, public dev::eth::AccountHolder { Q_OBJECT public: - OurWebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3, - std::vector const& _accounts, Main* main); - - virtual std::string shh_newIdentity() override; - virtual void authenticate(dev::eth::TransactionSkeleton const& _t, bool _toProxy); - -signals: - void onNewId(QString _s); + OurAccountHolder( + dev::WebThreeDirect& _web3, + Main* _main + ); public slots: void doValidations(); +protected: + // easiest to return keyManager.addresses(); + virtual dev::AddressHash realAccounts() const override; + // use web3 to submit a signed transaction to accept + virtual void authenticate(dev::eth::TransactionSkeleton const& _t) override; + private: bool showAuthenticationPopup(std::string const& _title, std::string const& _text); bool showCreationNotice(dev::eth::TransactionSkeleton const& _t, bool _toProxy); @@ -53,9 +56,29 @@ private: bool validateTransaction(dev::eth::TransactionSkeleton const& _t, bool _toProxy); - std::queue> m_queued; + std::queue m_queued; dev::Mutex x_queued; dev::WebThreeDirect* m_web3; Main* m_main; }; + +class OurWebThreeStubServer: public QObject, public WebThreeStubServer +{ + Q_OBJECT + +public: + OurWebThreeStubServer( + jsonrpc::AbstractServerConnector& _conn, + dev::WebThreeDirect& _web3, + Main* main + ); + + virtual std::string shh_newIdentity() override; + +signals: + void onNewId(QString _s); + +private: + Main* m_main; +}; diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index 2041bf39d..bc37db8ef 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #if ETH_SERPENT #include #include @@ -69,11 +70,20 @@ Transact::~Transact() delete ui; } -void Transact::setEnvironment(QList _myKeys, dev::eth::Client* _eth, NatSpecFace* _natSpecDB) +void Transact::setEnvironment(AddressHash const& _accounts, dev::eth::Client* _eth, NatSpecFace* _natSpecDB) { - m_myKeys = _myKeys; + m_accounts = _accounts; m_ethereum = _eth; m_natSpecDB = _natSpecDB; + + ui->from->clear(); + for (auto const& i: m_accounts) + { + auto d = m_context->keyManager().accountDetails()[i]; + u256 b = ethereum()->balanceAt(i, PendingBlock); + QString s = QString("%4 %2: %1").arg(formatBalance(b).c_str()).arg(QString::fromStdString(m_context->render(i))).arg(QString::fromStdString(d.first)); + ui->from->addItem(s); + } } bool Transact::isCreation() const @@ -126,8 +136,8 @@ void Transact::updateFee() 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) + for (auto const& i: m_accounts) + if (ethereum()->balanceAt(i) >= totalReq) { ok = true; break; @@ -388,22 +398,33 @@ Secret Transact::findSecret(u256 _totalReq) const if (!ethereum()) return Secret(); - Secret best; + Address best; u256 bestBalance = 0; - for (auto const& i: m_myKeys) + for (auto const& i: m_accounts) { - auto b = ethereum()->balanceAt(i.address(), PendingBlock); + auto b = ethereum()->balanceAt(i, PendingBlock); if (b >= _totalReq) - return i.secret(); + { + best = i; + break; + } if (b > bestBalance) - bestBalance = b, best = i.secret(); + bestBalance = b, best = i; } - return best; + return m_context->retrieveSecret(best); +} + +Address Transact::fromAccount() +{ + auto it = m_accounts.begin(); + std::advance(it, ui->from->currentIndex()); + return *it; } void Transact::on_send_clicked() { - Secret s = findSecret(value() + fee()); +// Secret s = findSecret(value() + fee()); + Secret s = m_context->retrieveSecret(fromAccount()); auto b = ethereum()->balanceAt(KeyPair(s).address(), PendingBlock); if (!s || b < value() + fee()) { @@ -440,9 +461,10 @@ void Transact::on_send_clicked() void Transact::on_debug_clicked() { - Secret s = findSecret(value() + fee()); - auto b = ethereum()->balanceAt(KeyPair(s).address(), PendingBlock); - if (!s || b < value() + fee()) +// Secret s = findSecret(value() + fee()); + Address from = fromAccount(); + auto b = ethereum()->balanceAt(from, PendingBlock); + if (!from || b < value() + fee()) { QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction: no single account contains at least the required amount."); return; @@ -452,8 +474,9 @@ void Transact::on_debug_clicked() { State st(ethereum()->postState()); 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().toStdString()).first, m_data, st.transactionsFrom(dev::toAddress(s)), s); + Transaction(value(), gasPrice(), ui->gas->value(), m_data, st.transactionsFrom(from)) : + Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText().toStdString()).first, m_data, st.transactionsFrom(from)); + t.forceSender(from); Debugger dw(m_context, this); Executive e(st, ethereum()->blockChain(), 0); dw.populate(e, t); diff --git a/alethzero/Transact.h b/alethzero/Transact.h index 71bc393b2..cd62c0e20 100644 --- a/alethzero/Transact.h +++ b/alethzero/Transact.h @@ -41,7 +41,7 @@ public: explicit Transact(Context* _context, QWidget* _parent = 0); ~Transact(); - void setEnvironment(QList _myKeys, dev::eth::Client* _eth, NatSpecFace* _natSpecDB); + void setEnvironment(dev::AddressHash const& _accounts, dev::eth::Client* _eth, NatSpecFace* _natSpecDB); private slots: void on_destination_currentTextChanged(QString); @@ -60,6 +60,7 @@ private: dev::eth::Client* ethereum() const { return m_ethereum; } void rejigData(); + dev::Address fromAccount(); void updateDestination(); void updateFee(); bool isCreation() const; @@ -76,7 +77,7 @@ private: unsigned m_backupGas = 0; dev::bytes m_data; - QList m_myKeys; + dev::AddressHash m_accounts; dev::eth::Client* m_ethereum = nullptr; Context* m_context = nullptr; NatSpecFace* m_natSpecDB = nullptr; diff --git a/alethzero/Transact.ui b/alethzero/Transact.ui index 75af9ba98..f7a5e7c0e 100644 --- a/alethzero/Transact.ui +++ b/alethzero/Transact.ui @@ -14,91 +14,69 @@ Transact - - - - + + + + + 0 + 0 + - - 430000000 + + D&ata - - 0 + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + data - - + + - &Amount + &Optimise - - value + + true - - - - false + + + + gas - - true + + 1 - - + + 430000000 + + + 10000 - - - - Qt::Vertical + + + + &Cancel + + + Esc - - - QFrame::NoFrame - - - 0 - - - - - Qt::ClickFocus - - - QFrame::NoFrame - - - 0 - - - true - - - - - - - - - - 0 - 0 - - + + - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + &Debug - + @@ -114,53 +92,68 @@ - - - - - + + + + + 0 + 0 + + - &Debug + - - - - &Execute + + + + - - false + + 430000000 + + + 0 + + + - + - &Gas + &Amount - gas + value - - - - gas - - - 1 + + + + &Execute - - 430000000 + + false - - 10000 + + + + + + true + + + (Create Contract) + + - + @ @@ -173,49 +166,63 @@ - - - - &Optimise - - - true + + + + Qt::Vertical + + + QFrame::NoFrame + + + 0 + + + + + Qt::ClickFocus + + + QFrame::NoFrame + + + 0 + + + true + + - - - - 0 - 0 - - + - D&ata - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + &Gas - data + gas - - - + + + + false + + true - - - (Create Contract) - - + + + - - + + + + + 0 @@ -225,18 +232,24 @@ + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + - - + + - &Cancel + &From - - Esc + + from + + + diff --git a/appdmg.json.in b/appdmg.json.in new file mode 100644 index 000000000..4fb9a6e33 --- /dev/null +++ b/appdmg.json.in @@ -0,0 +1,13 @@ +{ + "title": "Ethereum", + "icon": "appdmg_icon.icns", + "background": "appdmg_background.png", + "icon-size": 80, + "contents": [ + { "x": 600, "y": 170, "type": "link", "path": "/Applications" }, + { "x": 150, "y": 90, "type": "file", "path": "${ETH_ALETHZERO_APP}" }, + { "x": 150, "y": 260, "type": "file", "path": "${ETH_MIX_APP}" } + ] +} + + diff --git a/bg.png b/bg.png new file mode 100644 index 000000000..869290c2b Binary files /dev/null and b/bg.png differ diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 9e9ae687e..0d6fd7907 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -55,6 +55,7 @@ endif () if (PROFILING AND (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))) set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}") + set(CMAKE_C_FLAGS "-g ${CMAKE_C_FLAGS}") add_definitions(-DETH_PROFILING_GPERF) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lprofiler") # set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} -lprofiler") diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 2dfb80ac3..7f0578c1f 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -31,7 +31,8 @@ endif() # homebrew installs qts in opt if (APPLE) - set (CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "/usr/local/opt/qt5") + set (CMAKE_PREFIX_PATH "/usr/local/opt/qt5" ${CMAKE_PREFIX_PATH}) + set (CMAKE_PREFIX_PATH "/usr/local/opt/v8-315" ${CMAKE_PREFIX_PATH}) endif() find_program(CTEST_COMMAND ctest) @@ -47,6 +48,13 @@ find_package (LevelDB REQUIRED) message(" - LevelDB header: ${LEVELDB_INCLUDE_DIRS}") message(" - LevelDB lib: ${LEVELDB_LIBRARIES}") +if (JSCONSOLE) + find_package (v8 REQUIRED) + message(" - v8 header: ${V8_INCLUDE_DIRS}") + message(" - v8 lib : ${V8_LIBRARIES}") + add_definitions(-DETH_JSCONSOLE) +endif() + # TODO the Jsoncpp package does not yet check for correct version number find_package (Jsoncpp 0.60 REQUIRED) message(" - Jsoncpp header: ${JSONCPP_INCLUDE_DIRS}") @@ -151,6 +159,11 @@ if (GUI) message(" - windeployqt path: ${WINDEPLOYQT_APP}") endif() + if (APPLE) + find_program(ETH_APP_DMG appdmg) + message(" - appdmg location : ${ETH_APP_DMG}") + endif() + if (USENPM) # TODO check node && npm version diff --git a/cmake/Findv8.cmake b/cmake/Findv8.cmake new file mode 100644 index 000000000..2451c708f --- /dev/null +++ b/cmake/Findv8.cmake @@ -0,0 +1,49 @@ +# Find v8 +# +# Find the v8 includes and library +# +# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH +# +# This module defines +# V8_INCLUDE_DIRS, where to find header, etc. +# V8_LIBRARIES, the libraries needed to use v8. +# V8_FOUND, If false, do not try to use v8. + +# only look in default directories +find_path( + V8_INCLUDE_DIR + NAMES v8.h + DOC "v8 include dir" +) + +find_library( + V8_LIBRARY + NAMES v8 + DOC "v8 library" +) + +set(V8_INCLUDE_DIRS ${V8_INCLUDE_DIR}) +set(V8_LIBRARIES ${V8_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" +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + + find_library( + V8_LIBRARY_DEBUG + NAMES v8d + DOC "v8 debug library" + ) + + set(V8_LIBRARIES optimized ${V8_LIBRARIES} debug ${V8_LIBRARY_DEBUG}) + +endif() + +# handle the QUIETLY and REQUIRED arguments and set V8_FOUND to TRUE +# if all listed variables are TRUE, hide their existence from configuration view +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(v8 DEFAULT_MSG + V8_INCLUDE_DIR V8_LIBRARY) +mark_as_advanced (V8_INCLUDE_DIR V8_LIBRARY) + diff --git a/cmake/scripts/appdmg.cmake b/cmake/scripts/appdmg.cmake new file mode 100644 index 000000000..d9826ae9d --- /dev/null +++ b/cmake/scripts/appdmg.cmake @@ -0,0 +1,17 @@ + +if (NOT APP_DMG_EXE) + message(FATAL_ERROR "Please install appdmg! https://github.com/LinusU/node-appdmg") +endif() + +string(REPLACE "/Contents/MacOS" "" ETH_MIX_APP "${ETH_MIX_APP}") +string(REPLACE "/Contents/MacOS" "" ETH_ALETHZERO_APP "${ETH_ALETHZERO_APP}") + +set(OUTFILE "${ETH_BUILD_DIR}/appdmg.json") + +configure_file(${APP_DMG_FILE} ${OUTFILE}) + +execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${APP_DMG_ICON}" "${ETH_BUILD_DIR}/appdmg_icon.icns") +execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${APP_DMG_BACKGROUND}" "${ETH_BUILD_DIR}/appdmg_background.png") +execute_process(COMMAND ${CMAKE_COMMAND} -E remove "${ETH_BUILD_DIR}/Ethereum.dmg") +execute_process(COMMAND ${APP_DMG_EXE} ${OUTFILE} "${ETH_BUILD_DIR}/Ethereum.dmg") + diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 0e56eb9f5..d317be28a 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -7,6 +7,10 @@ include_directories(BEFORE ..) include_directories(${Boost_INCLUDE_DIRS}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) +if (JSCONSOLE) + include_directories(${V8_INCLUDE_DIRS}) +endif() + set(EXECUTABLE eth) file(GLOB HEADERS "*.h") @@ -33,6 +37,10 @@ endif() target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} ethash) +if (JSCONSOLE) + target_link_libraries(${EXECUTABLE} jsconsole) +endif() + if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) eth_copy_dlls("${EXECUTABLE}" MHD_DLLS) endif() diff --git a/eth/main.cpp b/eth/main.cpp index cb051aad1..d6582e4d3 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -37,12 +37,17 @@ #include #include #include +#include #include +#if ETH_JSCONSOLE || !ETH_TRUE +#include +#endif #if ETH_READLINE || !ETH_TRUE #include #include #endif #if ETH_JSONRPC || !ETH_TRUE +#include #include #include #include @@ -86,10 +91,8 @@ void interactiveHelp() << " minestart Starts mining." << endl << " minestop Stops mining." << endl << " mineforce Forces mining, even when there are no transactions." << endl - << " address Gives the current address." << endl - << " secret Gives the current secret" << endl << " block Gives the current block height." << endl - << " balance Gives the current balance." << endl + << " accounts Gives information on all owned accounts (balances, mining beneficiary and default signer)." << endl << " transact Execute a given transaction." << endl << " send Execute a given transaction with current secret." << endl << " contract Create a new contract with current secret." << endl @@ -98,7 +101,7 @@ void interactiveHelp() << " listaccounts List the accounts on the network." << endl << " listcontracts List the contracts on the network." << endl #endif - << " setsecret Set the secret to the hex secret key." << endl + << " setsigningkey Set the address with which to sign transactions." << endl << " setaddress Set the coinbase (mining payout) address." << endl << " exportconfig Export the config (.RLP) to the path provided." << endl << " importconfig Import the config (.RLP) from the path provided." << endl @@ -122,12 +125,18 @@ void help() #endif << " -K,--kill First kill the blockchain." << endl << " -R,--rebuild Rebuild the blockchain from the existing database." << endl - << " -s,--secret Set the secret key for use with send command (default: auto)." << endl - << " -S,--session-secret Set the secret key for use with send command, for this session only." << endl + << " -s,--import-secret Import a secret key into the key store and use as the default." << endl + << " -S,--import-session-secret Import a secret key into the key store and use as the default for this session only." << endl + << " --sign-key
Sign all transactions with the key of the given address." << endl + << " --session-sign-key
Sign all transactions with the key of the given address for this session only." << endl + << " --master Give the master password for the key store." << endl + << " --password Give a password for a private key." << endl + << endl << "Client transacting:" << endl << " -B,--block-fees Set the block fee profit in the reference unit e.g. ¢ (default: 15)." << endl << " -e,--ether-price Set the ether price in the reference unit e.g. ¢ (default: 30.679)." << endl << " -P,--priority <0 - 100> Default % priority of a transaction (default: 50)." << endl + << endl << "Client mining:" << endl << " -a,--address Set the coinbase (mining payout) address to addr (default: auto)." << endl << " -m,--mining Enable mining, optionally for a specified number of blocks (default: off)" << endl @@ -137,6 +146,7 @@ void help() << " --opencl-platform When mining using -G/--opencl use OpenCL platform n (default: 0)." << endl << " --opencl-device When mining using -G/--opencl use OpenCL device n (default: 0)." << endl << " -t, --mining-threads Limit number of CPU/GPU miners to n (default: use everything available on selected platform)" << endl + << endl << "Client networking:" << endl << " --client-name Add a name to your client's version string (default: blank)." << endl << " -b,--bootstrap Connect to the default Ethereum peerserver." << endl @@ -149,12 +159,15 @@ void help() << " --network-id Only connect to other hosts with this network id (default:0)." << endl << " --upnp Use UPnP for NAT (default: on)." << endl #if ETH_JSONRPC || !ETH_TRUE + << endl << "Work farming mode:" << endl << " -F,--farm Put into mining farm mode with the work server at URL. Use with -G/--opencl." << endl << " --farm-recheck Leave n ms between checks for changed work (default: 500)." << endl #endif + << endl << "Ethash verify mode:" << endl << " -w,--check-pow Check PoW credentials for validity." << endl + << endl << "Benchmarking mode:" << endl << " -M,--benchmark Benchmark for mining and exit; use with --cpu and --opencl." << endl << " --benchmark-warmup Set the duration of warmup for the benchmark tests (default: 3)." << endl @@ -163,14 +176,17 @@ void help() #if ETH_JSONRPC || !ETH_TRUE << " --phone-home When benchmarking, publish results (default: on)" << endl #endif + << endl << "DAG creation mode:" << endl << " -D,--create-dag Create the DAG in preparation for mining on given block and exit." << endl + << endl << "Import/export modes:" << endl << " -I,--import Import file as a concatenated series of blocks and exit." << endl << " -E,--export Export file as a concatenated series of blocks and exit." << endl << " --from Export only from block n; n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl << " --to Export only to block n (inclusive); n may be a decimal, a '0x' prefixed hash, or 'latest'." << endl << " --only Equivalent to --export-from n --export-to n." << endl + << endl << "General Options:" << endl << " -d,--db-path Load database from path (default: " << getDataDir() << ")" << endl #if ETH_EVMJIT || !ETH_TRUE @@ -179,6 +195,9 @@ void help() << " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (default: 8)." << endl << " -V,--version Show the version and exit." << endl << " -h,--help Show this help message and exit." << endl +#if ETH_JSCONSOLE || !ETH_TRUE + << " --console Use interactive javascript console" << endl +#endif ; exit(0); } @@ -406,6 +425,13 @@ void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod) exit(0); } +void stopMiningAfterXBlocks(eth::Client* _c, unsigned _start, unsigned _mining) +{ + if (_c->isMining() && _c->blockChain().details().number - _start == _mining) + _c->stopMining(); + this_thread::sleep_for(chrono::milliseconds(100)); +} + int main(int argc, char** argv) { #if 0 @@ -523,13 +549,14 @@ int main(int argc, char** argv) /// Mining params unsigned mining = 0; bool forceMining = false; - KeyPair sigKey = KeyPair::create(); - Secret sessionSecret; - Address coinbase = sigKey.address(); + Address signingKey; + Address sessionKey; + Address beneficiary = signingKey; /// Structured logging params bool structuredLogging = false; string structuredLoggingFormat = "%Y-%m-%dT%H:%M:%S"; + string structuredLoggingURL; /// Transaction params TransactionPriority priority = TransactionPriority::Medium; @@ -542,17 +569,32 @@ int main(int argc, char** argv) unsigned benchmarkTrial = 3; unsigned benchmarkTrials = 5; + // javascript console + bool useConsole = false; + /// Farm params string farmURL = "http://127.0.0.1:8080"; unsigned farmRecheckPeriod = 500; + /// Wallet password stuff + string masterPassword; + string configFile = getDataDir() + "/config.rlp"; bytes b = contents(configFile); + + strings passwordsToNote; + Secrets toImport; if (b.size()) { RLP config(b); - sigKey = KeyPair(config[0].toHash()); - coinbase = config[1].toHash
(); + if (config[0].size() == 32) // secret key - import and forget. + { + Secret s = config[0].toHash(); + toImport.push_back(s); + } + else // new format - just use it as an address. + signingKey = config[0].toHash
(); + beneficiary = config[1].toHash
(); } for (int i = 1; i < argc; ++i) @@ -580,6 +622,10 @@ int main(int argc, char** argv) cerr << "-p is DEPRECATED. It will be removed for the Frontier. Use --port instead (or place directly as host:port)." << endl; remotePort = (short)atoi(argv[++i]); } + else if (arg == "--password" && i + 1 < argc) + passwordsToNote.push_back(argv[++i]); + else if (arg == "--master" && i + 1 < argc) + masterPassword = argv[++i]; else if ((arg == "-I" || arg == "--import") && i + 1 < argc) { mode = OperationMode::Import; @@ -720,7 +766,7 @@ int main(int argc, char** argv) } else if ((arg == "-a" || arg == "--address" || arg == "--coinbase-address") && i + 1 < argc) try { - coinbase = h160(fromHex(argv[++i], WhenError::Throw)); + beneficiary = h160(fromHex(argv[++i], WhenError::Throw)); } catch (BadHexCharacter&) { @@ -736,14 +782,32 @@ int main(int argc, char** argv) minerType = MinerType::CPU; else if (arg == "-G" || arg == "--opencl") minerType = MinerType::GPU; - else if ((arg == "-s" || arg == "--secret") && i + 1 < argc) - sigKey = KeyPair(h256(fromHex(argv[++i]))); - else if ((arg == "-S" || arg == "--session-secret") && i + 1 < argc) - sessionSecret = h256(fromHex(argv[++i])); + /*<< " -s,--import-secret Import a secret key into the key store and use as the default." << endl + << " -S,--import-session-secret Import a secret key into the key store and use as the default for this session only." << endl + << " --sign-key
Sign all transactions with the key of the given address." << endl + << " --session-sign-key
Sign all transactions with the key of the given address for this session only." << endl*/ + else if ((arg == "-s" || arg == "--import-secret") && i + 1 < argc) + { + Secret s(fromHex(argv[++i])); + toImport.push_back(s); + signingKey = toAddress(s); + } + else if ((arg == "-S" || arg == "--import-session-secret") && i + 1 < argc) + { + Secret s(fromHex(argv[++i])); + toImport.push_back(s); + sessionKey = toAddress(s); + } + else if ((arg == "--sign-key") && i + 1 < argc) + sessionKey = Address(fromHex(argv[++i])); + else if ((arg == "--session-sign-key") && i + 1 < argc) + sessionKey = Address(fromHex(argv[++i])); else if (arg == "--structured-logging-format" && i + 1 < argc) structuredLoggingFormat = string(argv[++i]); else if (arg == "--structured-logging") structuredLogging = true; + else if (arg == "--structured-logging-destination" && i + 1 < argc) + structuredLoggingURL = argv[++i]; else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc) dbPath = argv[++i]; else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc) @@ -784,7 +848,7 @@ int main(int argc, char** argv) auto boundary = bi.boundary(); m = boost::to_lower_copy(string(argv[++i])); bi.nonce = h64(m); - auto r = EthashAux::eval(seedHash, powHash, bi.nonce); + auto r = EthashAux::eval((uint64_t)bi.number, powHash, bi.nonce); bool valid = r.value < boundary; cout << (valid ? "VALID :-)" : "INVALID :-(") << endl; cout << r.value << (valid ? " < " : " >= ") << boundary << endl; @@ -793,7 +857,7 @@ int main(int argc, char** argv) cout << " with seed as " << seedHash << endl; if (valid) cout << "(mixHash = " << r.mixHash << ")" << endl; - cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(seedHash)->data()) << endl; + cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light((uint64_t)bi.number)->data()) << endl; exit(0); } catch (...) @@ -888,6 +952,10 @@ int main(int argc, char** argv) jsonrpc = jsonrpc == -1 ? SensibleHttpPort : jsonrpc; else if (arg == "--json-rpc-port" && i + 1 < argc) jsonrpc = atoi(argv[++i]); +#endif +#if ETH_JSCONSOLE + else if (arg == "--console") + useConsole = true; #endif else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc) g_logVerbosity = atoi(argv[++i]); @@ -923,16 +991,24 @@ int main(int argc, char** argv) } } + KeyManager keyManager; + for (auto const& s: passwordsToNote) + keyManager.notePassword(s); + for (auto const& s: toImport) + { + keyManager.import(s, "Imported key"); + if (!signingKey) + signingKey = toAddress(s); + } + { RLPStream config(2); - config << sigKey.secret() << coinbase; + config << signingKey << beneficiary; writeFile(configFile, config.out()); } - if (sessionSecret) - sigKey = KeyPair(sessionSecret); - - + if (sessionKey) + signingKey = sessionKey; if (minerType == MinerType::CPU) ProofOfWork::CPUMiner::setNumInstances(miningThreads); @@ -957,7 +1033,7 @@ int main(int argc, char** argv) if (!clientName.empty()) clientName += "/"; - StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat); + StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat, structuredLoggingURL); VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter); auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp); auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp"); @@ -1046,27 +1122,68 @@ int main(int argc, char** argv) c->setGasPricer(gasPricer); c->setForceMining(forceMining); c->setTurboMining(minerType == MinerType::GPU); - c->setAddress(coinbase); + c->setAddress(beneficiary); c->setNetworkId(networkId); } - cout << "Transaction Signer: " << sigKey.address() << endl; - cout << "Mining Benefactor: " << coinbase << endl; + cout << "Transaction Signer: " << signingKey << endl; + cout << "Mining Benefactor: " << beneficiary << endl; web3.startNetwork(); cout << "Node ID: " << web3.enode() << endl; if (bootstrap) - web3.addNode(p2p::NodeId(), Host::pocHost()); + for (auto const& i: Host::pocHosts()) + web3.requirePeer(i.first, i.second); if (remoteHost.size()) web3.addNode(p2p::NodeId(), remoteHost + ":" + toString(remotePort)); -#if ETH_JSONRPC + if (keyManager.exists()) + while (masterPassword.empty()) + { + masterPassword = getPassword("Please enter your MASTER password: "); + if (!keyManager.load(masterPassword)) + { + cout << "Password invalid. Try again." << endl; + masterPassword.clear(); + } + } + else + { + while (masterPassword.empty()) + { + masterPassword = getPassword("Please enter a MASTER password to protect your key store (make it strong!): "); + string confirm = getPassword("Please confirm the password by entering it again: "); + if (masterPassword != confirm) + { + cout << "Passwords were different. Try again." << endl; + masterPassword.clear(); + } + } + keyManager.create(masterPassword); + } + + string logbuf; + bool silence = false; + std::string additional; + g_logPost = [&](std::string const& a, char const*) { if (silence) logbuf += a + "\n"; else cout << "\r \r" << a << endl << additional << flush; }; + + // TODO: give hints &c. + auto getPassword = [&](Address const& a){ + auto s = silence; + silence = true; + cout << endl; + string ret = dev::getPassword("Enter password for address " + keyManager.accountDetails()[a].first + " (" + a.abridged() + "; hint:" + keyManager.accountDetails()[a].second + "): "); + silence = s; + return ret; + }; + +#if ETH_JSONRPC || !ETH_TRUE shared_ptr jsonrpcServer; unique_ptr jsonrpcConnector; if (jsonrpc > -1) { jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads)); - jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, vector({sigKey}))); + jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared([&](){return web3.ethereum();}, getPassword, keyManager), vector())); jsonrpcServer->StartListening(); } #endif @@ -1077,15 +1194,15 @@ int main(int argc, char** argv) if (interactive) { - string logbuf; + additional = "Press Enter"; string l; while (!g_exit) { - g_logPost = [](std::string const& a, char const*) { cout << "\r \r" << a << endl << "Press Enter" << flush; }; + silence = false; cout << logbuf << "Press Enter" << flush; std::getline(cin, l); logbuf.clear(); - g_logPost = [&](std::string const& a, char const*) { logbuf += a + "\n"; }; + silence = true; #if ETH_READLINE if (l.size()) @@ -1198,7 +1315,7 @@ int main(int argc, char** argv) iss >> g_logVerbosity; cout << "Verbosity: " << g_logVerbosity << endl; } -#if ETH_JSONRPC +#if ETH_JSONRPC || !ETH_TRUE else if (cmd == "jsonport") { if (iss.peek() != -1) @@ -1210,7 +1327,7 @@ int main(int argc, char** argv) if (jsonrpc < 0) jsonrpc = SensibleHttpPort; jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads)); - jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, vector({sigKey}))); + jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared([&](){return web3.ethereum();}, getPassword, keyManager), vector())); jsonrpcServer->StartListening(); } else if (cmd == "jsonstop") @@ -1222,11 +1339,8 @@ int main(int argc, char** argv) #endif else if (cmd == "address") { - cout << "Current address:" << endl << sigKey.address() << endl; - } - else if (cmd == "secret") - { - cout << "Secret Key: " << sigKey.secret() << endl; + cout << "Current mining beneficiary:" << endl << beneficiary << endl; + cout << "Current signing account:" << endl << signingKey << endl; } else if (c && cmd == "block") { @@ -1241,7 +1355,15 @@ int main(int argc, char** argv) } else if (c && cmd == "balance") { - cout << "Current balance: " << formatBalance( c->balanceAt(sigKey.address())) << " = " <balanceAt(sigKey.address()) << " wei" << endl; + cout << "Current balance:" << endl; + u256 total = 0; + for (auto const& i: keyManager.accountDetails()) + { + auto b = c->balanceAt(i.first); + cout << ((i.first == signingKey) ? "SIGNING " : " ") << ((i.first == beneficiary) ? "COINBASE " : " ") << i.second.first << " (" << i.first << "): " << formatBalance(b) << " = " << b << " wei" << endl; + total += b; + } + cout << "Total: " << formatBalance(total) << " = " << total << " wei" << endl; } else if (c && cmd == "transact") { @@ -1357,7 +1479,7 @@ int main(int argc, char** argv) try { Address dest = h160(fromHex(hexAddr, WhenError::Throw)); - c->submitTransaction(sigKey.secret(), amount, dest, bytes(), minGas); + c->submitTransaction(keyManager.secret(signingKey, [&](){ return getPassword(signingKey); }), amount, dest, bytes(), minGas); } catch (BadHexCharacter& _e) { @@ -1426,7 +1548,7 @@ int main(int argc, char** argv) else if (gas < minGas) cwarn << "Minimum gas amount is" << minGas; else - c->submitTransaction(sigKey.secret(), endowment, init, gas, gasPrice); + c->submitTransaction(keyManager.secret(signingKey, [&](){ return getPassword(signingKey); }), endowment, init, gas, gasPrice); } else cwarn << "Require parameters: contract ENDOWMENT GASPRICE GAS CODEHEX"; @@ -1537,13 +1659,13 @@ int main(int argc, char** argv) } } } - else if (cmd == "setsecret") + else if (cmd == "setsigningkey") { if (iss.peek() != -1) { string hexSec; iss >> hexSec; - sigKey = KeyPair(h256(fromHex(hexSec))); + signingKey = Address(fromHex(hexSec)); } else cwarn << "Require parameter: setSecret HEXSECRETKEY"; @@ -1560,7 +1682,7 @@ int main(int argc, char** argv) { try { - coinbase = h160(fromHex(hexAddr, WhenError::Throw)); + beneficiary = h160(fromHex(hexAddr, WhenError::Throw)); } catch (BadHexCharacter& _e) { @@ -1583,7 +1705,7 @@ int main(int argc, char** argv) string path; iss >> path; RLPStream config(2); - config << sigKey.secret() << coinbase; + config << signingKey << beneficiary; writeFile(path, config.out()); } else @@ -1599,8 +1721,8 @@ int main(int argc, char** argv) if (b.size()) { RLP config(b); - sigKey = KeyPair(config[0].toHash()); - coinbase = config[1].toHash
(); + signingKey = config[0].toHash
(); + beneficiary = config[1].toHash
(); } else cwarn << path << "has no content!"; @@ -1625,12 +1747,20 @@ int main(int argc, char** argv) unsigned n =c->blockChain().details().number; if (mining) c->startMining(); - while (!g_exit) + if (useConsole) { - if ( c->isMining() &&c->blockChain().details().number - n == mining) - c->stopMining(); - this_thread::sleep_for(chrono::milliseconds(100)); +#if ETH_JSCONSOLE + JSConsole console(web3, vector({sigKey})); + while (!g_exit) + { + console.repl(); + stopMiningAfterXBlocks(c, n, mining); + } +#endif } + else + while (!g_exit) + stopMiningAfterXBlocks(c, n, mining); } else while (!g_exit) diff --git a/ethminer/main.cpp b/ethminer/main.cpp index 02ccf2dd8..124d3f779 100644 --- a/ethminer/main.cpp +++ b/ethminer/main.cpp @@ -417,7 +417,7 @@ int main(int argc, char** argv) auto boundary = bi.boundary(); m = boost::to_lower_copy(string(argv[++i])); bi.nonce = h64(m); - auto r = EthashAux::eval(seedHash, powHash, bi.nonce); + auto r = EthashAux::eval((uint64_t)bi.number, powHash, bi.nonce); bool valid = r.value < boundary; cout << (valid ? "VALID :-)" : "INVALID :-(") << endl; cout << r.value << (valid ? " < " : " >= ") << boundary << endl; @@ -426,7 +426,7 @@ int main(int argc, char** argv) cout << " with seed as " << seedHash << endl; if (valid) cout << "(mixHash = " << r.mixHash << ")" << endl; - cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(seedHash)->data()) << endl; + cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light((uint64_t)bi.number)->data()) << endl; exit(0); } catch (...) diff --git a/exp/main.cpp b/exp/main.cpp index 973679f3d..2bd0a741e 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -42,10 +42,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -64,87 +66,26 @@ namespace fs = boost::filesystem; #if 1 -inline h128 fromUUID(std::string const& _uuid) { return h128(boost::replace_all_copy(_uuid, "-", "")); } - -class KeyManager: public Worker +int main() { -public: - KeyManager() { readKeys(); } - ~KeyManager() {} - - Secret secret(h128 const& _uuid, std::string const& _pass) - { - auto it = m_keys.find(_uuid); - if (it == m_keys.end()) - return Secret(); - return Secret(decrypt(it->second, _pass)); - } - -private: - void readKeys(std::string const& _keysPath = getDataDir("web3") + "/keys") - { - fs::path p(_keysPath); - js::mValue v; - for (fs::directory_iterator it(p); it != fs::directory_iterator(); ++it) - if (is_regular_file(it->path())) - { - cdebug << "Reading" << it->path(); - js::read_string(contentsString(it->path().string()), v); - js::mObject o = v.get_obj(); - int version = o.count("Version") ? stoi(o["Version"].get_str()) : o.count("version") ? o["version"].get_int() : 0; - if (version == 2) - m_keys[fromUUID(o["id"].get_str())] = o["crypto"]; - else - cwarn << "Cannot read key version" << version; - } - } - - static bytes decrypt(js::mValue const& _v, std::string const& _pass) - { - js::mObject o = _v.get_obj(); - bytes pKey; - if (o["kdf"].get_str() == "pbkdf2") - { - auto params = o["kdfparams"].get_obj(); - unsigned iterations = params["c"].get_int(); - bytes salt = fromHex(params["salt"].get_str()); - pKey = pbkdf2(_pass, salt, iterations).asBytes(); - } - else - { - cwarn << "Unknown KDF" << o["kdf"].get_str() << "not supported."; - return bytes(); - } + KeyManager keyman; + if (keyman.exists()) + keyman.load("foo"); + else + keyman.create("foo"); - // TODO check MAC - h256 mac(o["mac"].get_str()); - (void)mac; + Address a("9cab1cc4e8fe528267c6c3af664a1adbce810b5f"); - bytes cipherText = fromHex(o["ciphertext"].get_str()); - bytes ret; - if (o["cipher"].get_str() == "aes-128-cbc") - { - auto params = o["cipherparams"].get_obj(); - h128 key(sha3(h128(pKey, h128::AlignRight)), h128::AlignRight); - h128 iv(params["iv"].get_str()); - decryptSymNoAuth(key, iv, &cipherText, ret); - } - else - { - cwarn << "Unknown cipher" << o["cipher"].get_str() << "not supported."; - return bytes(); - } +// keyman.importExisting(fromUUID("441193ae-a767-f1c3-48ba-dd6610db5ed0"), "{\"name\":\"Gavin Wood - Main identity\"}", "bar", "{\"hint\":\"Not foo.\"}"); +// Address a2 = keyman.address(keyman.import(Secret::random(), "Key with no additional security.")); +// cdebug << toString(a2); + Address a2("19c486071651b2650449ba3c6a807f316a73e8fe"); - return ret; - } + cdebug << keyman.accountDetails(); - std::map m_keys; -}; + cdebug << "Secret key for " << a << "is" << keyman.secret(a, [](){ return "bar"; }); + cdebug << "Secret key for " << a2 << "is" << keyman.secret(a2); -int main() -{ - KeyManager keyman; - cdebug << "Secret key for 0498f19a-59db-4d54-ac95-33901b4f1870 is " << keyman.secret(fromUUID("0498f19a-59db-4d54-ac95-33901b4f1870"), "foo"); } #elif 0 diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index be8152b55..06950cbee 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -28,7 +28,9 @@ using namespace dev; namespace dev { -char const* Version = "0.9.15"; +char const* Version = "0.9.18"; + +const u256 UndefinedU256 = ~(u256)0; void HasInvariants::checkInvariants() const { diff --git a/libdevcore/Common.h b/libdevcore/Common.h index e0872b5d4..41f1b1d49 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -34,10 +34,13 @@ #endif #include +#include #include #include +#include #include #include +#include #pragma warning(push) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" @@ -79,11 +82,17 @@ using u160s = std::vector; using u256Set = std::set; using u160Set = std::set; +extern const u256 UndefinedU256; + // Map types. using StringMap = std::map; using u256Map = std::map; using HexMap = std::map; +// Hash types. +using StringHashMap = std::unordered_map; +using u256HashMap = std::unordered_map; + // String types. using strings = std::vector; @@ -215,4 +224,14 @@ inline dev::WithExisting max(dev::WithExisting _a, dev::WithExisting _b) return static_cast(max(static_cast(_a), static_cast(_b))); } +template <> struct hash +{ + size_t operator()(dev::u256 const& _a) const + { + unsigned size = _a.backend().size(); + auto limbs = _a.backend().limbs(); + return boost::hash_range(limbs, limbs + size); + } +}; + } diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h index a0ea01a1b..6c1f34667 100644 --- a/libdevcore/CommonData.h +++ b/libdevcore/CommonData.h @@ -258,6 +258,14 @@ template std::set& operator+=(std::set& _a, U const& _b return _a; } +/// Insert the contents of a container into an unordered_st +template std::unordered_set& operator+=(std::unordered_set& _a, U const& _b) +{ + for (auto const& i: _b) + _a.insert(i); + return _a; +} + /// Concatenate the contents of a container onto a vector template std::vector& operator+=(std::vector& _a, U const& _b) { diff --git a/libdevcore/CommonIO.cpp b/libdevcore/CommonIO.cpp index a1a1056cb..80ad7ecf9 100644 --- a/libdevcore/CommonIO.cpp +++ b/libdevcore/CommonIO.cpp @@ -20,7 +20,8 @@ */ #include "CommonIO.h" - +#include +#include #include #include "Exceptions.h" using namespace std; @@ -117,3 +118,14 @@ void dev::writeFile(std::string const& _file, bytesConstRef _data) ofstream(_file, ios::trunc|ios::binary).write((char const*)_data.data(), _data.size()); } +std::string dev::getPassword(std::string const& _prompt) +{ +#if WIN32 + cout << _prompt << flush; + std::string ret; + std::getline(cin, ret); + return ret; +#else + return getpass(_prompt.c_str()); +#endif +} diff --git a/libdevcore/CommonIO.h b/libdevcore/CommonIO.h index 80334fa31..46a8b80bc 100644 --- a/libdevcore/CommonIO.h +++ b/libdevcore/CommonIO.h @@ -42,6 +42,8 @@ namespace dev { +std::string getPassword(std::string const& _prompt); + /// Retrieve and returns the contents of the given file. If the file doesn't exist or isn't readable, returns an empty bytes. bytes contents(std::string const& _file); std::string contentsString(std::string const& _file); diff --git a/libdevcore/FixedHash.cpp b/libdevcore/FixedHash.cpp index ae2d77c85..6c2a9a57e 100644 --- a/libdevcore/FixedHash.cpp +++ b/libdevcore/FixedHash.cpp @@ -19,10 +19,25 @@ * @date 2014 */ -#include #include "FixedHash.h" +#include +#include using namespace std; using namespace dev; std::random_device dev::s_fixedHashEngine; + +h128 dev::fromUUID(std::string const& _uuid) +{ + return h128(boost::replace_all_copy(_uuid, "-", "")); +} + +std::string dev::toUUID(h128 const& _uuid) +{ + std::string ret = toHex(_uuid.ref()); + for (unsigned i: {20, 16, 12, 8}) + ret.insert(ret.begin() + i, '-'); + return ret; +} + diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h index 2cf81cb77..9b25837af 100644 --- a/libdevcore/FixedHash.h +++ b/libdevcore/FixedHash.h @@ -113,6 +113,9 @@ public: /// @returns an abridged version of the hash as a user-readable hex string. std::string abridged() const { return toHex(ref().cropped(0, 4)) + "\342\200\246"; } + /// @returns an abridged version of the hash as a user-readable hex string. + std::string hex() const { return toHex(ref()); } + /// @returns a mutable byte vector_ref to the object's data. bytesRef ref() { return bytesRef(m_data.data(), N); } @@ -147,17 +150,10 @@ public: /// @returns a random valued object. static FixedHash random() { return random(s_fixedHashEngine); } - /// A generic std::hash compatible function object. struct hash { /// Make a hash of the object's data. - size_t operator()(FixedHash const& value) const - { - size_t h = 0; - for (auto i: value.m_data) - h = (h << (5 - h)) + i; - return h; - } + size_t operator()(FixedHash const& _value) const { return boost::hash_range(_value.m_data.cbegin(), _value.m_data.cend()); } }; template inline FixedHash& shiftBloom(FixedHash const& _h) @@ -218,12 +214,8 @@ template<> inline bool FixedHash<32>::operator==(FixedHash<32> const& _other) co /// Fast std::hash compatible hash function object for h256. template<> inline size_t FixedHash<32>::hash::operator()(FixedHash<32> const& value) const { - const uint64_t*data = (const uint64_t*)value.data(); - uint64_t hash = data[0]; - hash ^= data[1]; - hash ^= data[2]; - hash ^= data[3]; - return (size_t)hash; + uint64_t const* data = reinterpret_cast(value.data()); + return boost::hash_range(data, data + 4); } /// Stream I/O for the FixedHash class. @@ -251,6 +243,8 @@ using h256s = std::vector; using h160s = std::vector; using h256Set = std::set; using h160Set = std::set; +using h256Hash = std::unordered_set; +using h160Hash = std::unordered_set; /// Convert the given value into h160 (160-bit unsigned integer) using the right 20 bytes. inline h160 right160(h256 const& _t) @@ -268,6 +262,10 @@ inline h160 left160(h256 const& _t) return ret; } +h128 fromUUID(std::string const& _uuid); + +std::string toUUID(h128 const& _uuid); + inline std::string toString(h256s const& _bs) { std::ostringstream out; @@ -282,6 +280,10 @@ inline std::string toString(h256s const& _bs) namespace std { - /// Forward std::hash to dev::h256::hash. + /// Forward std::hash to dev::FixedHash::hash. + template<> struct hash: dev::h64::hash {}; + template<> struct hash: dev::h128::hash {}; + template<> struct hash: dev::h160::hash {}; template<> struct hash: dev::h256::hash {}; + template<> struct hash: dev::h512::hash {}; } diff --git a/libdevcore/Log.h b/libdevcore/Log.h index f42e9cbdd..20ad9fd20 100644 --- a/libdevcore/Log.h +++ b/libdevcore/Log.h @@ -164,6 +164,30 @@ public: } m_sstr << EthLime "}" EthReset; } + template void append(std::unordered_set const& _t) + { + m_sstr << EthYellow "{" EthReset; + int n = 0; + for (auto const& i: _t) + { + m_sstr << (n++ ? EthYellow ", " EthReset : ""); + append(i); + } + m_sstr << EthYellow "}" EthReset; + } + template void append(std::unordered_map const& _t) + { + m_sstr << EthLime "{" EthReset; + int n = 0; + for (auto const& i: _t) + { + m_sstr << (n++ ? EthLime ", " EthReset : ""); + append(i.first); + m_sstr << (n++ ? EthLime ": " EthReset : ""); + append(i.second); + } + m_sstr << EthLime "}" EthReset; + } template void append(std::pair const& _t) { m_sstr << EthPurple "(" EthReset; diff --git a/libdevcore/RLP.h b/libdevcore/RLP.h index ac5e2ef1e..6e46807ab 100644 --- a/libdevcore/RLP.h +++ b/libdevcore/RLP.h @@ -362,6 +362,7 @@ public: template RLPStream& appendVector(std::vector<_T> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; } template RLPStream& append(std::array<_T, S> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; } template RLPStream& append(std::set<_T> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; } + template RLPStream& append(std::unordered_set<_T> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; } template RLPStream& append(std::pair const& _s) { appendList(2); append(_s.first); append(_s.second); return *this; } /// Appends a list. diff --git a/libdevcore/StructuredLogger.cpp b/libdevcore/StructuredLogger.cpp index f51ed310a..7d8a17722 100644 --- a/libdevcore/StructuredLogger.cpp +++ b/libdevcore/StructuredLogger.cpp @@ -34,6 +34,15 @@ using namespace std; namespace dev { +void StructuredLogger::initialize(bool _enabled, std::string const& _timeFormat, std::string const& _destinationURL) +{ + m_enabled = _enabled; + m_timeFormat = _timeFormat; + if (_destinationURL.size() > 7 && _destinationURL.substr(0, 7) == "file://") + m_out.open(_destinationURL.substr(7)); + // TODO: support tcp:// +} + void StructuredLogger::outputJson(Json::Value const& _value, std::string const& _name) const { Json::Value event; @@ -41,7 +50,7 @@ void StructuredLogger::outputJson(Json::Value const& _value, std::string const& Json::FastWriter fastWriter; Guard l(s_lock); event[_name] = _value; - cout << fastWriter.write(event) << endl; + (m_out.is_open() ? m_out : cout) << fastWriter.write(event) << endl; } void StructuredLogger::starting(string const& _clientImpl, const char* _ethVersion) @@ -51,6 +60,7 @@ void StructuredLogger::starting(string const& _clientImpl, const char* _ethVersi Json::Value event; event["client_impl"] = _clientImpl; event["eth_version"] = std::string(_ethVersion); + // TODO net_version event["ts"] = dev::toString(chrono::system_clock::now(), get().m_timeFormat.c_str()); get().outputJson(event, "starting"); @@ -64,6 +74,7 @@ void StructuredLogger::stopping(string const& _clientImpl, const char* _ethVersi Json::Value event; event["client_impl"] = _clientImpl; event["eth_version"] = std::string(_ethVersion); + // TODO net_version event["ts"] = dev::toString(chrono::system_clock::now(), get().m_timeFormat.c_str()); get().outputJson(event, "stopping"); diff --git a/libdevcore/StructuredLogger.h b/libdevcore/StructuredLogger.h index 2c30541e4..913d7b9b2 100644 --- a/libdevcore/StructuredLogger.h +++ b/libdevcore/StructuredLogger.h @@ -25,6 +25,7 @@ #pragma once +#include #include #include @@ -46,11 +47,7 @@ public: * http://en.cppreference.com/w/cpp/chrono/c/strftime * with which to display timestamps */ - void initialize(bool _enabled, std::string const& _timeFormat) - { - m_enabled = _enabled; - m_timeFormat = _timeFormat; - } + void initialize(bool _enabled, std::string const& _timeFormat, std::string const& _destinationURL = ""); static StructuredLogger& get() { @@ -92,6 +89,11 @@ public: std::string const& _prevHash ); static void transactionReceived(std::string const& _hash, std::string const& _remoteId); + // TODO: static void pendingQueueChanged(std::vector const& _hashes); + // TODO: static void miningStarted(); + // TODO: static void stillMining(unsigned _hashrate); + // TODO: static void miningStopped(); + private: // Singleton class. Private default ctor and no copying StructuredLogger() = default; @@ -102,6 +104,8 @@ private: bool m_enabled = false; std::string m_timeFormat = "%Y-%m-%dT%H:%M:%S"; + + mutable std::ofstream m_out; }; } diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index 48dd5c384..a5c176fe6 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -20,6 +20,7 @@ * @date 2014 */ +#include "Common.h" #include #include #include @@ -28,7 +29,6 @@ #include "SHA3.h" #include "FileSystem.h" #include "CryptoPP.h" -#include "Common.h" using namespace std; using namespace dev; using namespace dev::crypto; @@ -112,51 +112,47 @@ bool dev::decryptSym(Secret const& _k, bytesConstRef _cipher, bytes& o_plain) return decrypt(_k, _cipher, o_plain); } -h128 dev::encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher) +std::pair dev::encryptSymNoAuth(h128 const& _k, bytesConstRef _plain) { h128 iv(Nonce::get()); - return encryptSymNoAuth(_k, _plain, o_cipher, iv); + return make_pair(encryptSymNoAuth(_k, iv, _plain), iv); } -h128 dev::encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher, h128 const& _iv) +bytes dev::encryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _plain) { - o_cipher.resize(_plain.size()); - const int c_aesKeyLen = 16; SecByteBlock key(_k.data(), c_aesKeyLen); try { CTR_Mode::Encryption e; e.SetKeyWithIV(key, key.size(), _iv.data()); - e.ProcessData(o_cipher.data(), _plain.data(), _plain.size()); - return _iv; + bytes ret(_plain.size()); + e.ProcessData(ret.data(), _plain.data(), _plain.size()); + return ret; } catch (CryptoPP::Exception& _e) { cerr << _e.what() << endl; - o_cipher.resize(0); - return h128(); + return bytes(); } } -bool dev::decryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _cipher, bytes& o_plaintext) +bytes dev::decryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _cipher) { - o_plaintext.resize(_cipher.size()); - const size_t c_aesKeyLen = 16; SecByteBlock key(_k.data(), c_aesKeyLen); try { CTR_Mode::Decryption d; d.SetKeyWithIV(key, key.size(), _iv.data()); - d.ProcessData(o_plaintext.data(), _cipher.data(), _cipher.size()); - return true; + bytes ret(_cipher.size()); + d.ProcessData(ret.data(), _cipher.data(), _cipher.size()); + return ret; } catch (CryptoPP::Exception& _e) { cerr << _e.what() << endl; - o_plaintext.resize(0); - return false; + return bytes(); } } @@ -175,11 +171,11 @@ bool dev::verify(Public const& _p, Signature const& _s, h256 const& _hash) return s_secp256k1.verify(_p, _s, _hash.ref(), true); } -h256 dev::pbkdf2(string const& _pass, bytes const& _salt, unsigned _iterations) +bytes dev::pbkdf2(string const& _pass, bytes const& _salt, unsigned _iterations, unsigned _dkLen) { - h256 ret; + bytes ret(_dkLen); PKCS5_PBKDF2_HMAC pbkdf; - pbkdf.DeriveKey(ret.data(), ret.size, 0, (byte*)_pass.data(), _pass.size(), _salt.data(), _salt.size(), _iterations); + pbkdf.DeriveKey(ret.data(), ret.size(), 0, (byte*)_pass.data(), _pass.size(), _salt.data(), _salt.size(), _iterations); return ret; } diff --git a/libdevcrypto/Common.h b/libdevcrypto/Common.h index 50072c1bf..6464c7ede 100644 --- a/libdevcrypto/Common.h +++ b/libdevcrypto/Common.h @@ -68,8 +68,8 @@ extern Address ZeroAddress; /// A vector of Ethereum addresses. using Addresses = h160s; -/// A set of Ethereum addresses. -using AddressSet = std::set; +/// A hash set of Ethereum addresses. +using AddressHash = std::unordered_set; /// A vector of secrets. using Secrets = h256s; @@ -103,13 +103,13 @@ void encryptECIES(Public const& _k, bytesConstRef _plain, bytes& o_cipher); bool decryptECIES(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext); /// Encrypts payload with random IV/ctr using AES128-CTR. -h128 encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher); +std::pair encryptSymNoAuth(h128 const& _k, bytesConstRef _plain); /// Encrypts payload with specified IV/ctr using AES128-CTR. -h128 encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher, h128 const& _iv); - +bytes encryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _plain); + /// Decrypts payload with specified IV/ctr using AES128-CTR. -bool decryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _cipher, bytes& o_plaintext); +bytes decryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _cipher); /// Recovers Public key from signed message hash. Public recover(Signature const& _sig, h256 const& _hash); @@ -121,7 +121,7 @@ Signature sign(Secret const& _k, h256 const& _hash); bool verify(Public const& _k, Signature const& _s, h256 const& _hash); /// Derive key via PBKDF2. -h256 pbkdf2(std::string const& _pass, bytes const& _salt, unsigned _iterations); +bytes pbkdf2(std::string const& _pass, bytes const& _salt, unsigned _iterations, unsigned _dkLen = 32); /// Simple class that represents a "key pair". /// All of the data of the class can be regenerated from the secret key (m_secret) alone. diff --git a/libdevcrypto/CryptoPP.cpp b/libdevcrypto/CryptoPP.cpp index e89857502..b701fed8d 100644 --- a/libdevcrypto/CryptoPP.cpp +++ b/libdevcrypto/CryptoPP.cpp @@ -78,8 +78,7 @@ void Secp256k1::encryptECIES(Public const& _k, bytes& io_cipher) bytes mKey(32); ctx.Final(mKey.data()); - bytes cipherText; - encryptSymNoAuth(h128(eKey), bytesConstRef(&io_cipher), cipherText, h128()); + bytes cipherText = encryptSymNoAuth(h128(eKey), h128(), bytesConstRef(&io_cipher)); if (cipherText.empty()) return; @@ -139,7 +138,7 @@ bool Secp256k1::decryptECIES(Secret const& _k, bytes& io_text) if (mac[i] != msgMac[i]) return false; - decryptSymNoAuth(h128(eKey), iv, cipherNoIV, plain); + plain = decryptSymNoAuth(h128(eKey), iv, cipherNoIV); io_text.resize(plain.size()); io_text.swap(plain); diff --git a/libdevcrypto/MemoryDB.cpp b/libdevcrypto/MemoryDB.cpp index 907e6abe6..4b08db083 100644 --- a/libdevcrypto/MemoryDB.cpp +++ b/libdevcrypto/MemoryDB.cpp @@ -30,9 +30,9 @@ namespace dev const char* DBChannel::name() { return "TDB"; } const char* DBWarn::name() { return "TDB"; } -std::map MemoryDB::get() const +std::unordered_map MemoryDB::get() const { - std::map ret; + std::unordered_map ret; for (auto const& i: m_main) if (!m_enforceRefs || i.second.second > 0) ret.insert(make_pair(i.first, i.second.first)); @@ -112,9 +112,9 @@ void MemoryDB::purge() it = m_main.erase(it); } -set MemoryDB::keys() const +h256Hash MemoryDB::keys() const { - set ret; + h256Hash ret; for (auto const& i: m_main) if (i.second.second) ret.insert(i.first); diff --git a/libdevcrypto/MemoryDB.h b/libdevcrypto/MemoryDB.h index 71428ecdb..3169d8fbc 100644 --- a/libdevcrypto/MemoryDB.h +++ b/libdevcrypto/MemoryDB.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include #include #include @@ -45,7 +45,7 @@ public: MemoryDB() {} void clear() { m_main.clear(); } // WARNING !!!! didn't originally clear m_refCount!!! - std::map get() const; + std::unordered_map get() const; std::string lookup(h256 const& _h) const; bool exists(h256 const& _h) const; @@ -57,11 +57,11 @@ public: void removeAux(h256 const& _h) { m_aux[_h].second = false; } void insertAux(h256 const& _h, bytesConstRef _v) { m_aux[_h] = make_pair(_v.toBytes(), true); } - std::set keys() const; + h256Hash keys() const; protected: - std::map> m_main; - std::map> m_aux; + std::unordered_map> m_main; + std::unordered_map> m_aux; mutable bool m_enforceRefs = false; }; diff --git a/libdevcrypto/SecretStore.cpp b/libdevcrypto/SecretStore.cpp new file mode 100644 index 000000000..9be0b89e8 --- /dev/null +++ b/libdevcrypto/SecretStore.cpp @@ -0,0 +1,221 @@ +/* + 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 . +*/ +/** @file SecretStore.cpp + * @author Gav Wood + * @date 2014 + */ + +#include "SecretStore.h" +#include +#include +#include +#include +#include +#include +#include "SHA3.h" +#include "FileSystem.h" +using namespace std; +using namespace dev; +namespace js = json_spirit; +namespace fs = boost::filesystem; + +SecretStore::SecretStore() +{ + load(); +} + +SecretStore::~SecretStore() +{ +} + +bytes SecretStore::secret(h128 const& _uuid, function const& _pass) const +{ + auto rit = m_cached.find(_uuid); + if (rit != m_cached.end()) + return rit->second; + auto it = m_keys.find(_uuid); + if (it == m_keys.end()) + return bytes(); + bytes key = decrypt(it->second.first, _pass()); + if (!key.empty()) + m_cached[_uuid] = key; + return key; +} + +h128 SecretStore::importSecret(bytes const& _s, std::string const& _pass) +{ + h128 r = h128::random(); + m_cached[r] = _s; + m_keys[r] = make_pair(encrypt(_s, _pass), std::string()); + save(); + return r; +} + +void SecretStore::kill(h128 const& _uuid) +{ + m_cached.erase(_uuid); + if (m_keys.count(_uuid)) + { + boost::filesystem::remove(m_keys[_uuid].second); + m_keys.erase(_uuid); + } +} + +void SecretStore::clearCache() const +{ + m_cached.clear(); +} + +void SecretStore::save(std::string const& _keysPath) +{ + fs::path p(_keysPath); + boost::filesystem::create_directories(p); + for (auto& k: m_keys) + { + std::string uuid = toUUID(k.first); + std::string filename = (p / uuid).string() + ".json"; + js::mObject v; + js::mValue crypto; + js::read_string(k.second.first, crypto); + v["crypto"] = crypto; + v["id"] = uuid; + v["version"] = 2; + writeFile(filename, js::write_string(js::mValue(v), true)); + if (!k.second.second.empty() && k.second.second != filename) + boost::filesystem::remove(k.second.second); + k.second.second = filename; + } +} + +void SecretStore::load(std::string const& _keysPath) +{ + fs::path p(_keysPath); + boost::filesystem::create_directories(p); + js::mValue v; + for (fs::directory_iterator it(p); it != fs::directory_iterator(); ++it) + if (is_regular_file(it->path())) + { + cdebug << "Reading" << it->path(); + js::read_string(contentsString(it->path().string()), v); + if (v.type() == js::obj_type) + { + js::mObject o = v.get_obj(); + int version = o.count("Version") ? stoi(o["Version"].get_str()) : o.count("version") ? o["version"].get_int() : 0; + if (version == 2) + m_keys[fromUUID(o["id"].get_str())] = make_pair(js::write_string(o["crypto"], false), it->path().string()); + else + cwarn << "Cannot read key version" << version; + } +// else +// cwarn << "Invalid JSON in key file" << it->path().string(); + } +} + +std::string SecretStore::encrypt(bytes const& _v, std::string const& _pass) +{ + js::mObject ret; + + // KDF info + unsigned dklen = 16; + unsigned iterations = 262144; + bytes salt = h256::random().asBytes(); + ret["kdf"] = "pbkdf2"; + { + js::mObject params; + params["prf"] = "hmac-sha256"; + params["c"] = (int)iterations; + params["salt"] = toHex(salt); + params["dklen"] = (int)dklen; + ret["kdfparams"] = params; + } + bytes derivedKey = pbkdf2(_pass, salt, iterations, dklen); + + // cipher info + ret["cipher"] = "aes-128-cbc"; + h128 key(sha3(h128(derivedKey, h128::AlignRight)), h128::AlignRight); + h128 iv = h128::random(); + { + js::mObject params; + params["iv"] = toHex(iv.ref()); + ret["cipherparams"] = params; + } + + // cipher text + bytes cipherText = encryptSymNoAuth(key, iv, &_v); + ret["ciphertext"] = toHex(cipherText); + + // and mac. + h256 mac = sha3(bytesConstRef(&derivedKey).cropped(derivedKey.size() - 16).toBytes() + cipherText); + ret["mac"] = toHex(mac.ref()); + + return js::write_string((js::mValue)ret, true); +} + +bytes SecretStore::decrypt(std::string const& _v, std::string const& _pass) +{ + js::mObject o; + { + js::mValue ov; + js::read_string(_v, ov); + o = ov.get_obj(); + } + + // derive key + bytes derivedKey; + if (o["kdf"].get_str() == "pbkdf2") + { + auto params = o["kdfparams"].get_obj(); + if (params["prf"].get_str() != "hmac-sha256") + { + cwarn << "Unknown PRF for PBKDF2" << params["prf"].get_str() << "not supported."; + return bytes(); + } + unsigned iterations = params["c"].get_int(); + bytes salt = fromHex(params["salt"].get_str()); + derivedKey = pbkdf2(_pass, salt, iterations, params["dklen"].get_int()); + } + else + { + cwarn << "Unknown KDF" << o["kdf"].get_str() << "not supported."; + return bytes(); + } + + bytes cipherText = fromHex(o["ciphertext"].get_str()); + + // check MAC + h256 mac(o["mac"].get_str()); + h256 macExp = sha3(bytesConstRef(&derivedKey).cropped(derivedKey.size() - 16).toBytes() + cipherText); + if (mac != macExp) + { + cwarn << "Invalid key - MAC mismatch; expected" << toString(macExp) << ", got" << toString(mac); + return bytes(); + } + + // decrypt + if (o["cipher"].get_str() == "aes-128-cbc") + { + auto params = o["cipherparams"].get_obj(); + h128 key(sha3(h128(derivedKey, h128::AlignRight)), h128::AlignRight); + h128 iv(params["iv"].get_str()); + return decryptSymNoAuth(key, iv, &cipherText); + } + else + { + cwarn << "Unknown cipher" << o["cipher"].get_str() << "not supported."; + return bytes(); + } +} diff --git a/libdevcrypto/SecretStore.h b/libdevcrypto/SecretStore.h new file mode 100644 index 000000000..1fb6adf4a --- /dev/null +++ b/libdevcrypto/SecretStore.h @@ -0,0 +1,57 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . + */ +/** @file SecretStore.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#include +#include +#include +#include "Common.h" +#include "FileSystem.h" + +namespace dev +{ + +class SecretStore +{ +public: + SecretStore(); + ~SecretStore(); + + bytes secret(h128 const& _uuid, std::function const& _pass) const; + h128 importSecret(bytes const& _s, std::string const& _pass); + void kill(h128 const& _uuid); + + // Clear any cached keys. + void clearCache() const; + +private: + void save(std::string const& _keysPath = getDataDir("web3") + "/keys"); + void load(std::string const& _keysPath = getDataDir("web3") + "/keys"); + static std::string encrypt(bytes const& _v, std::string const& _pass); + static bytes decrypt(std::string const& _v, std::string const& _pass); + + mutable std::unordered_map m_cached; + std::unordered_map> m_keys; +}; + +} + diff --git a/libdevcrypto/TrieDB.h b/libdevcrypto/TrieDB.h index ef628d20b..ff2bcc589 100644 --- a/libdevcrypto/TrieDB.h +++ b/libdevcrypto/TrieDB.h @@ -26,7 +26,6 @@ #include #pragma warning(pop) -#include #include #include #include @@ -105,7 +104,7 @@ public: void debugPrint() {} - void descendKey(h256 _k, std::set& _keyMask, bool _wasExt, std::ostream* _out, int _indent = 0) const + void descendKey(h256 _k, h256Hash& _keyMask, bool _wasExt, std::ostream* _out, int _indent = 0) const { _keyMask.erase(_k); if (_k == m_root && _k == c_shaNull) // root allowed to be empty @@ -113,7 +112,7 @@ public: descendList(RLP(node(_k)), _keyMask, _wasExt, _out, _indent); // if not, it must be a list } - void descendEntry(RLP const& _r, std::set& _keyMask, bool _wasExt, std::ostream* _out, int _indent) const + void descendEntry(RLP const& _r, h256Hash& _keyMask, bool _wasExt, std::ostream* _out, int _indent) const { if (_r.isData() && _r.size() == 32) descendKey(_r.toHash(), _keyMask, _wasExt, _out, _indent); @@ -123,7 +122,7 @@ public: BOOST_THROW_EXCEPTION(InvalidTrie()); } - void descendList(RLP const& _r, std::set& _keyMask, bool _wasExt, std::ostream* _out, int _indent) const + void descendList(RLP const& _r, h256Hash& _keyMask, bool _wasExt, std::ostream* _out, int _indent) const { if (_r.isList() && _r.itemCount() == 2 && (!_wasExt || _out)) { @@ -144,9 +143,9 @@ public: BOOST_THROW_EXCEPTION(InvalidTrie()); } - std::set leftOvers(std::ostream* _out = nullptr) const + h256Hash leftOvers(std::ostream* _out = nullptr) const { - std::set k = m_db->keys(); + h256Hash k = m_db->keys(); descendKey(m_root, k, false, _out); return k; } @@ -431,7 +430,7 @@ public: void insert(bytesConstRef _key, bytesConstRef _value) { Super::insert(_key, _value); m_secure.insert(_key, _value); syncRoot(); } void remove(bytesConstRef _key) { Super::remove(_key); m_secure.remove(_key); syncRoot(); } - std::set leftOvers(std::ostream* = nullptr) const { return std::set{}; } + h256Hash leftOvers(std::ostream* = nullptr) const { return h256Hash{}; } bool check(bool) const { return m_secure.check(false) && Super::check(false); } private: diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 42098e09d..79efbcb97 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -119,9 +120,7 @@ unsigned ethash_cl_miner::get_num_devices(unsigned _platformId) void ethash_cl_miner::finish() { if (m_queue()) - { m_queue.finish(); - } } bool ethash_cl_miner::init(uint8_t const* _dag, uint64_t _dagSize, unsigned workgroup_size, unsigned _platformId, unsigned _deviceId) @@ -161,9 +160,7 @@ bool ethash_cl_miner::init(uint8_t const* _dag, uint64_t _dagSize, unsigned work return false; } if (strncmp("OpenCL 1.1", device_version.c_str(), 10) == 0) - { m_opencl_1_1 = true; - } // create context m_context = cl::Context(std::vector(&device, &device + 1)); @@ -306,21 +303,15 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook // update header constant buffer m_queue.enqueueWriteBuffer(m_header, false, 0, 32, header); for (unsigned i = 0; i != c_num_buffers; ++i) - { m_queue.enqueueWriteBuffer(m_search_buf[i], false, 0, 4, &c_zero); - } #if CL_VERSION_1_2 && 0 cl::Event pre_return_event; if (!m_opencl_1_1) - { m_queue.enqueueBarrierWithWaitList(NULL, &pre_return_event); - } else #endif - { m_queue.finish(); - } /* __kernel void ethash_combined_search( @@ -341,7 +332,9 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook unsigned buf = 0; - for (uint64_t start_nonce = 0; ; start_nonce += c_search_batch_size) + std::random_device engine; + uint64_t start_nonce = std::uniform_int_distribution()(engine); + for (; ; start_nonce += c_search_batch_size) { // supply output buffer to kernel m_search_kernel.setArg(0, m_search_buf[buf]); @@ -386,9 +379,7 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook // not safe to return until this is ready #if CL_VERSION_1_2 && 0 if (!m_opencl_1_1) - { pre_return_event.wait(); - } #endif } diff --git a/libethash/CMakeLists.txt b/libethash/CMakeLists.txt index 009cd2d92..907eccd40 100644 --- a/libethash/CMakeLists.txt +++ b/libethash/CMakeLists.txt @@ -10,8 +10,7 @@ if (NOT MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") endif() -set(FILES util.c - util.h +set(FILES util.h io.c internal.c ethash.h @@ -21,7 +20,7 @@ set(FILES util.c data_sizes.h) if (MSVC) - list(APPEND FILES io_win32.c) + list(APPEND FILES util_win32.c io_win32.c mmap_win32.c) else() list(APPEND FILES io_posix.c) endif() @@ -46,4 +45,4 @@ endif() if (NOT ETHASHCL) install( TARGETS ${LIBRARY} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) -endif () +endif () \ No newline at end of file diff --git a/libethash/data_sizes.h b/libethash/data_sizes.h index cf52ae4f8..83cc30bcb 100644 --- a/libethash/data_sizes.h +++ b/libethash/data_sizes.h @@ -49,416 +49,416 @@ extern "C" { static const uint64_t dag_sizes[2048] = { - 1073739904U, 1082130304U, 1090514816U, 1098906752U, 1107293056U, - 1115684224U, 1124070016U, 1132461952U, 1140849536U, 1149232768U, - 1157627776U, 1166013824U, 1174404736U, 1182786944U, 1191180416U, - 1199568512U, 1207958912U, 1216345216U, 1224732032U, 1233124736U, - 1241513344U, 1249902464U, 1258290304U, 1266673792U, 1275067264U, - 1283453312U, 1291844992U, 1300234112U, 1308619904U, 1317010048U, - 1325397376U, 1333787776U, 1342176128U, 1350561664U, 1358954368U, - 1367339392U, 1375731584U, 1384118144U, 1392507008U, 1400897408U, - 1409284736U, 1417673344U, 1426062464U, 1434451072U, 1442839168U, - 1451229056U, 1459615616U, 1468006016U, 1476394112U, 1484782976U, - 1493171584U, 1501559168U, 1509948032U, 1518337664U, 1526726528U, - 1535114624U, 1543503488U, 1551892096U, 1560278656U, 1568669056U, - 1577056384U, 1585446272U, 1593831296U, 1602219392U, 1610610304U, - 1619000192U, 1627386752U, 1635773824U, 1644164224U, 1652555648U, - 1660943488U, 1669332608U, 1677721216U, 1686109312U, 1694497664U, - 1702886272U, 1711274624U, 1719661184U, 1728047744U, 1736434816U, - 1744829056U, 1753218944U, 1761606272U, 1769995904U, 1778382464U, - 1786772864U, 1795157888U, 1803550592U, 1811937664U, 1820327552U, - 1828711552U, 1837102976U, 1845488768U, 1853879936U, 1862269312U, - 1870656896U, 1879048064U, 1887431552U, 1895825024U, 1904212096U, - 1912601216U, 1920988544U, 1929379456U, 1937765504U, 1946156672U, - 1954543232U, 1962932096U, 1971321728U, 1979707264U, 1988093056U, - 1996487552U, 2004874624U, 2013262208U, 2021653888U, 2030039936U, - 2038430848U, 2046819968U, 2055208576U, 2063596672U, 2071981952U, - 2080373632U, 2088762752U, 2097149056U, 2105539712U, 2113928576U, - 2122315136U, 2130700672U, 2139092608U, 2147483264U, 2155872128U, - 2164257664U, 2172642176U, 2181035392U, 2189426048U, 2197814912U, - 2206203008U, 2214587264U, 2222979712U, 2231367808U, 2239758208U, - 2248145024U, 2256527744U, 2264922752U, 2273312128U, 2281701248U, - 2290086272U, 2298476672U, 2306867072U, 2315251072U, 2323639168U, - 2332032128U, 2340420224U, 2348808064U, 2357196416U, 2365580416U, - 2373966976U, 2382363008U, 2390748544U, 2399139968U, 2407530368U, - 2415918976U, 2424307328U, 2432695424U, 2441084288U, 2449472384U, - 2457861248U, 2466247808U, 2474637184U, 2483026816U, 2491414144U, - 2499803776U, 2508191872U, 2516582272U, 2524970368U, 2533359232U, - 2541743488U, 2550134144U, 2558525056U, 2566913408U, 2575301504U, - 2583686528U, 2592073856U, 2600467328U, 2608856192U, 2617240448U, - 2625631616U, 2634022016U, 2642407552U, 2650796416U, 2659188352U, - 2667574912U, 2675965312U, 2684352896U, 2692738688U, 2701130624U, - 2709518464U, 2717907328U, 2726293376U, 2734685056U, 2743073152U, - 2751462016U, 2759851648U, 2768232832U, 2776625536U, 2785017728U, - 2793401984U, 2801794432U, 2810182016U, 2818571648U, 2826959488U, - 2835349376U, 2843734144U, 2852121472U, 2860514432U, 2868900992U, - 2877286784U, 2885676928U, 2894069632U, 2902451584U, 2910843008U, - 2919234688U, 2927622784U, 2936011648U, 2944400768U, 2952789376U, - 2961177728U, 2969565568U, 2977951616U, 2986338944U, 2994731392U, - 3003120256U, 3011508352U, 3019895936U, 3028287104U, 3036675968U, - 3045063808U, 3053452928U, 3061837696U, 3070228352U, 3078615424U, - 3087003776U, 3095394944U, 3103782272U, 3112173184U, 3120562048U, - 3128944768U, 3137339264U, 3145725056U, 3154109312U, 3162505088U, - 3170893184U, 3179280256U, 3187669376U, 3196056704U, 3204445568U, - 3212836736U, 3221224064U, 3229612928U, 3238002304U, 3246391168U, - 3254778496U, 3263165824U, 3271556224U, 3279944576U, 3288332416U, - 3296719232U, 3305110912U, 3313500032U, 3321887104U, 3330273152U, - 3338658944U, 3347053184U, 3355440512U, 3363827072U, 3372220288U, - 3380608384U, 3388997504U, 3397384576U, 3405774208U, 3414163072U, - 3422551936U, 3430937984U, 3439328384U, 3447714176U, 3456104576U, - 3464493952U, 3472883584U, 3481268864U, 3489655168U, 3498048896U, - 3506434432U, 3514826368U, 3523213952U, 3531603584U, 3539987072U, - 3548380288U, 3556763264U, 3565157248U, 3573545344U, 3581934464U, - 3590324096U, 3598712704U, 3607098752U, 3615488384U, 3623877248U, - 3632265856U, 3640646528U, 3649043584U, 3657430144U, 3665821568U, - 3674207872U, 3682597504U, 3690984832U, 3699367808U, 3707764352U, - 3716152448U, 3724541056U, 3732925568U, 3741318016U, 3749706368U, - 3758091136U, 3766481536U, 3774872704U, 3783260032U, 3791650432U, - 3800036224U, 3808427648U, 3816815488U, 3825204608U, 3833592704U, - 3841981568U, 3850370432U, 3858755968U, 3867147904U, 3875536256U, - 3883920512U, 3892313728U, 3900702592U, 3909087872U, 3917478784U, - 3925868416U, 3934256512U, 3942645376U, 3951032192U, 3959422336U, - 3967809152U, 3976200064U, 3984588416U, 3992974976U, 4001363584U, - 4009751168U, 4018141312U, 4026530432U, 4034911616U, 4043308928U, - 4051695488U, 4060084352U, 4068472448U, 4076862848U, 4085249408U, - 4093640576U, 4102028416U, 4110413696U, 4118805632U, 4127194496U, - 4135583104U, 4143971968U, 4152360832U, 4160746112U, 4169135744U, - 4177525888U, 4185912704U, 4194303616U, 4202691968U, 4211076736U, - 4219463552U, 4227855488U, 4236246656U, 4244633728U, 4253022848U, - 4261412224U, 4269799808U, 4278184832U, 4286578048U, 4294962304U, - 4303349632U, 4311743104U, 4320130432U, 4328521088U, 4336909184U, - 4345295488U, 4353687424U, 4362073472U, 4370458496U, 4378852736U, - 4387238528U, 4395630208U, 4404019072U, 4412407424U, 4420790656U, - 4429182848U, 4437571456U, 4445962112U, 4454344064U, 4462738048U, - 4471119232U, 4479516544U, 4487904128U, 4496289664U, 4504682368U, - 4513068416U, 4521459584U, 4529846144U, 4538232704U, 4546619776U, - 4555010176U, 4563402112U, 4571790208U, 4580174464U, 4588567936U, - 4596957056U, 4605344896U, 4613734016U, 4622119808U, 4630511488U, - 4638898816U, 4647287936U, 4655675264U, 4664065664U, 4672451968U, - 4680842624U, 4689231488U, 4697620352U, 4706007424U, 4714397056U, - 4722786176U, 4731173248U, 4739562368U, 4747951744U, 4756340608U, - 4764727936U, 4773114496U, 4781504384U, 4789894784U, 4798283648U, - 4806667648U, 4815059584U, 4823449472U, 4831835776U, 4840226176U, - 4848612224U, 4857003392U, 4865391488U, 4873780096U, 4882169728U, - 4890557312U, 4898946944U, 4907333248U, 4915722368U, 4924110976U, - 4932499328U, 4940889728U, 4949276032U, 4957666432U, 4966054784U, - 4974438016U, 4982831488U, 4991221376U, 4999607168U, 5007998848U, - 5016386432U, 5024763776U, 5033164672U, 5041544576U, 5049941888U, - 5058329728U, 5066717056U, 5075107456U, 5083494272U, 5091883904U, - 5100273536U, 5108662144U, 5117048192U, 5125436032U, 5133827456U, - 5142215296U, 5150605184U, 5158993024U, 5167382144U, 5175769472U, - 5184157568U, 5192543872U, 5200936064U, 5209324928U, 5217711232U, - 5226102656U, 5234490496U, 5242877312U, 5251263872U, 5259654016U, - 5268040832U, 5276434304U, 5284819328U, 5293209728U, 5301598592U, - 5309986688U, 5318374784U, 5326764416U, 5335151488U, 5343542144U, - 5351929472U, 5360319872U, 5368706944U, 5377096576U, 5385484928U, - 5393871232U, 5402263424U, 5410650496U, 5419040384U, 5427426944U, - 5435816576U, 5444205952U, 5452594816U, 5460981376U, 5469367936U, - 5477760896U, 5486148736U, 5494536832U, 5502925952U, 5511315328U, - 5519703424U, 5528089984U, 5536481152U, 5544869504U, 5553256064U, - 5561645696U, 5570032768U, 5578423936U, 5586811264U, 5595193216U, - 5603585408U, 5611972736U, 5620366208U, 5628750464U, 5637143936U, - 5645528192U, 5653921408U, 5662310272U, 5670694784U, 5679082624U, - 5687474048U, 5695864448U, 5704251008U, 5712641408U, 5721030272U, - 5729416832U, 5737806208U, 5746194304U, 5754583936U, 5762969984U, - 5771358592U, 5779748224U, 5788137856U, 5796527488U, 5804911232U, - 5813300608U, 5821692544U, 5830082176U, 5838468992U, 5846855552U, - 5855247488U, 5863636096U, 5872024448U, 5880411008U, 5888799872U, - 5897186432U, 5905576832U, 5913966976U, 5922352768U, 5930744704U, - 5939132288U, 5947522432U, 5955911296U, 5964299392U, 5972688256U, - 5981074304U, 5989465472U, 5997851008U, 6006241408U, 6014627968U, - 6023015552U, 6031408256U, 6039796096U, 6048185216U, 6056574848U, - 6064963456U, 6073351808U, 6081736064U, 6090128768U, 6098517632U, - 6106906496U, 6115289216U, 6123680896U, 6132070016U, 6140459648U, - 6148849024U, 6157237376U, 6165624704U, 6174009728U, 6182403712U, - 6190792064U, 6199176064U, 6207569792U, 6215952256U, 6224345216U, - 6232732544U, 6241124224U, 6249510272U, 6257899136U, 6266287744U, - 6274676864U, 6283065728U, 6291454336U, 6299843456U, 6308232064U, - 6316620928U, 6325006208U, 6333395584U, 6341784704U, 6350174848U, - 6358562176U, 6366951296U, 6375337856U, 6383729536U, 6392119168U, - 6400504192U, 6408895616U, 6417283456U, 6425673344U, 6434059136U, - 6442444672U, 6450837376U, 6459223424U, 6467613056U, 6476004224U, - 6484393088U, 6492781952U, 6501170048U, 6509555072U, 6517947008U, - 6526336384U, 6534725504U, 6543112832U, 6551500672U, 6559888768U, - 6568278656U, 6576662912U, 6585055616U, 6593443456U, 6601834112U, - 6610219648U, 6618610304U, 6626999168U, 6635385472U, 6643777408U, - 6652164224U, 6660552832U, 6668941952U, 6677330048U, 6685719424U, - 6694107776U, 6702493568U, 6710882176U, 6719274112U, 6727662976U, - 6736052096U, 6744437632U, 6752825984U, 6761213824U, 6769604224U, - 6777993856U, 6786383488U, 6794770816U, 6803158144U, 6811549312U, - 6819937664U, 6828326528U, 6836706176U, 6845101696U, 6853491328U, - 6861880448U, 6870269312U, 6878655104U, 6887046272U, 6895433344U, - 6903822208U, 6912212864U, 6920596864U, 6928988288U, 6937377152U, - 6945764992U, 6954149248U, 6962544256U, 6970928768U, 6979317376U, - 6987709312U, 6996093824U, 7004487296U, 7012875392U, 7021258624U, - 7029652352U, 7038038912U, 7046427776U, 7054818944U, 7063207808U, - 7071595136U, 7079980928U, 7088372608U, 7096759424U, 7105149824U, - 7113536896U, 7121928064U, 7130315392U, 7138699648U, 7147092352U, - 7155479168U, 7163865728U, 7172249984U, 7180648064U, 7189036672U, - 7197424768U, 7205810816U, 7214196608U, 7222589824U, 7230975104U, - 7239367552U, 7247755904U, 7256145536U, 7264533376U, 7272921472U, - 7281308032U, 7289694848U, 7298088832U, 7306471808U, 7314864512U, - 7323253888U, 7331643008U, 7340029568U, 7348419712U, 7356808832U, - 7365196672U, 7373585792U, 7381973888U, 7390362752U, 7398750592U, - 7407138944U, 7415528576U, 7423915648U, 7432302208U, 7440690304U, - 7449080192U, 7457472128U, 7465860992U, 7474249088U, 7482635648U, - 7491023744U, 7499412608U, 7507803008U, 7516192384U, 7524579968U, - 7532967296U, 7541358464U, 7549745792U, 7558134656U, 7566524032U, - 7574912896U, 7583300992U, 7591690112U, 7600075136U, 7608466816U, - 7616854912U, 7625244544U, 7633629824U, 7642020992U, 7650410368U, - 7658794112U, 7667187328U, 7675574912U, 7683961984U, 7692349568U, - 7700739712U, 7709130368U, 7717519232U, 7725905536U, 7734295424U, - 7742683264U, 7751069056U, 7759457408U, 7767849088U, 7776238208U, - 7784626816U, 7793014912U, 7801405312U, 7809792128U, 7818179968U, - 7826571136U, 7834957184U, 7843347328U, 7851732352U, 7860124544U, - 7868512384U, 7876902016U, 7885287808U, 7893679744U, 7902067072U, - 7910455936U, 7918844288U, 7927230848U, 7935622784U, 7944009344U, - 7952400256U, 7960786048U, 7969176704U, 7977565312U, 7985953408U, - 7994339968U, 8002730368U, 8011119488U, 8019508096U, 8027896192U, - 8036285056U, 8044674688U, 8053062272U, 8061448832U, 8069838464U, - 8078227328U, 8086616704U, 8095006592U, 8103393664U, 8111783552U, - 8120171392U, 8128560256U, 8136949376U, 8145336704U, 8153726848U, - 8162114944U, 8170503296U, 8178891904U, 8187280768U, 8195669632U, - 8204058496U, 8212444544U, 8220834176U, 8229222272U, 8237612672U, - 8246000768U, 8254389376U, 8262775168U, 8271167104U, 8279553664U, - 8287944064U, 8296333184U, 8304715136U, 8313108352U, 8321497984U, - 8329885568U, 8338274432U, 8346663296U, 8355052928U, 8363441536U, - 8371828352U, 8380217984U, 8388606592U, 8396996224U, 8405384576U, - 8413772672U, 8422161536U, 8430549376U, 8438939008U, 8447326592U, - 8455715456U, 8464104832U, 8472492928U, 8480882048U, 8489270656U, - 8497659776U, 8506045312U, 8514434944U, 8522823808U, 8531208832U, - 8539602304U, 8547990656U, 8556378752U, 8564768384U, 8573154176U, - 8581542784U, 8589933952U, 8598322816U, 8606705024U, 8615099264U, - 8623487872U, 8631876992U, 8640264064U, 8648653952U, 8657040256U, - 8665430656U, 8673820544U, 8682209152U, 8690592128U, 8698977152U, - 8707374464U, 8715763328U, 8724151424U, 8732540032U, 8740928384U, - 8749315712U, 8757704576U, 8766089344U, 8774480768U, 8782871936U, - 8791260032U, 8799645824U, 8808034432U, 8816426368U, 8824812928U, - 8833199488U, 8841591424U, 8849976448U, 8858366336U, 8866757248U, - 8875147136U, 8883532928U, 8891923328U, 8900306816U, 8908700288U, - 8917088384U, 8925478784U, 8933867392U, 8942250368U, 8950644608U, - 8959032704U, 8967420544U, 8975809664U, 8984197504U, 8992584064U, - 9000976256U, 9009362048U, 9017752448U, 9026141312U, 9034530688U, - 9042917504U, 9051307904U, 9059694208U, 9068084864U, 9076471424U, - 9084861824U, 9093250688U, 9101638528U, 9110027648U, 9118416512U, - 9126803584U, 9135188096U, 9143581312U, 9151969664U, 9160356224U, - 9168747136U, 9177134464U, 9185525632U, 9193910144U, 9202302848U, - 9210690688U, 9219079552U, 9227465344U, 9235854464U, 9244244864U, - 9252633472U, 9261021824U, 9269411456U, 9277799296U, 9286188928U, - 9294574208U, 9302965888U, 9311351936U, 9319740032U, 9328131968U, - 9336516736U, 9344907392U, 9353296768U, 9361685888U, 9370074752U, - 9378463616U, 9386849408U, 9395239808U, 9403629184U, 9412016512U, - 9420405376U, 9428795008U, 9437181568U, 9445570688U, 9453960832U, - 9462346624U, 9470738048U, 9479121536U, 9487515008U, 9495903616U, - 9504289664U, 9512678528U, 9521067904U, 9529456256U, 9537843584U, - 9546233728U, 9554621312U, 9563011456U, 9571398784U, 9579788672U, - 9588178304U, 9596567168U, 9604954496U, 9613343104U, 9621732992U, - 9630121856U, 9638508416U, 9646898816U, 9655283584U, 9663675776U, - 9672061312U, 9680449664U, 9688840064U, 9697230464U, 9705617536U, - 9714003584U, 9722393984U, 9730772608U, 9739172224U, 9747561088U, - 9755945344U, 9764338816U, 9772726144U, 9781116544U, 9789503872U, - 9797892992U, 9806282624U, 9814670464U, 9823056512U, 9831439232U, - 9839833984U, 9848224384U, 9856613504U, 9865000576U, 9873391232U, - 9881772416U, 9890162816U, 9898556288U, 9906940544U, 9915333248U, - 9923721088U, 9932108672U, 9940496512U, 9948888448U, 9957276544U, - 9965666176U, 9974048384U, 9982441088U, 9990830464U, 9999219584U, - 10007602816U, 10015996544U, 10024385152U, 10032774016U, 10041163648U, - 10049548928U, 10057940096U, 10066329472U, 10074717824U, 10083105152U, - 10091495296U, 10099878784U, 10108272256U, 10116660608U, 10125049216U, - 10133437312U, 10141825664U, 10150213504U, 10158601088U, 10166991232U, - 10175378816U, 10183766144U, 10192157312U, 10200545408U, 10208935552U, - 10217322112U, 10225712768U, 10234099328U, 10242489472U, 10250876032U, - 10259264896U, 10267656064U, 10276042624U, 10284429184U, 10292820352U, - 10301209472U, 10309598848U, 10317987712U, 10326375296U, 10334763392U, - 10343153536U, 10351541632U, 10359930752U, 10368318592U, 10376707456U, - 10385096576U, 10393484672U, 10401867136U, 10410262144U, 10418647424U, - 10427039104U, 10435425664U, 10443810176U, 10452203648U, 10460589952U, - 10468982144U, 10477369472U, 10485759104U, 10494147712U, 10502533504U, - 10510923392U, 10519313536U, 10527702656U, 10536091264U, 10544478592U, - 10552867712U, 10561255808U, 10569642368U, 10578032768U, 10586423168U, - 10594805632U, 10603200128U, 10611588992U, 10619976064U, 10628361344U, - 10636754048U, 10645143424U, 10653531776U, 10661920384U, 10670307968U, - 10678696832U, 10687086464U, 10695475072U, 10703863168U, 10712246144U, - 10720639616U, 10729026688U, 10737414784U, 10745806208U, 10754190976U, - 10762581376U, 10770971264U, 10779356288U, 10787747456U, 10796135552U, - 10804525184U, 10812915584U, 10821301888U, 10829692288U, 10838078336U, - 10846469248U, 10854858368U, 10863247232U, 10871631488U, 10880023424U, - 10888412032U, 10896799616U, 10905188992U, 10913574016U, 10921964672U, - 10930352768U, 10938742912U, 10947132544U, 10955518592U, 10963909504U, - 10972298368U, 10980687488U, 10989074816U, 10997462912U, 11005851776U, - 11014241152U, 11022627712U, 11031017344U, 11039403904U, 11047793024U, - 11056184704U, 11064570752U, 11072960896U, 11081343872U, 11089737856U, - 11098128256U, 11106514816U, 11114904448U, 11123293568U, 11131680128U, - 11140065152U, 11148458368U, 11156845696U, 11165236864U, 11173624192U, - 11182013824U, 11190402688U, 11198790784U, 11207179136U, 11215568768U, - 11223957376U, 11232345728U, 11240734592U, 11249122688U, 11257511296U, - 11265899648U, 11274285952U, 11282675584U, 11291065472U, 11299452544U, - 11307842432U, 11316231296U, 11324616832U, 11333009024U, 11341395584U, - 11349782656U, 11358172288U, 11366560384U, 11374950016U, 11383339648U, - 11391721856U, 11400117376U, 11408504192U, 11416893568U, 11425283456U, - 11433671552U, 11442061184U, 11450444672U, 11458837888U, 11467226752U, - 11475611776U, 11484003968U, 11492392064U, 11500780672U, 11509169024U, - 11517550976U, 11525944448U, 11534335616U, 11542724224U, 11551111808U, - 11559500672U, 11567890304U, 11576277376U, 11584667008U, 11593056128U, - 11601443456U, 11609830016U, 11618221952U, 11626607488U, 11634995072U, - 11643387776U, 11651775104U, 11660161664U, 11668552576U, 11676940928U, - 11685330304U, 11693718656U, 11702106496U, 11710496128U, 11718882688U, - 11727273088U, 11735660416U, 11744050048U, 11752437376U, 11760824704U, - 11769216128U, 11777604736U, 11785991296U, 11794381952U, 11802770048U, - 11811157888U, 11819548544U, 11827932544U, 11836324736U, 11844713344U, - 11853100928U, 11861486464U, 11869879936U, 11878268032U, 11886656896U, - 11895044992U, 11903433088U, 11911822976U, 11920210816U, 11928600448U, - 11936987264U, 11945375872U, 11953761152U, 11962151296U, 11970543488U, - 11978928512U, 11987320448U, 11995708288U, 12004095104U, 12012486272U, - 12020875136U, 12029255552U, 12037652096U, 12046039168U, 12054429568U, - 12062813824U, 12071206528U, 12079594624U, 12087983744U, 12096371072U, - 12104759936U, 12113147264U, 12121534592U, 12129924992U, 12138314624U, - 12146703232U, 12155091584U, 12163481216U, 12171864704U, 12180255872U, - 12188643968U, 12197034112U, 12205424512U, 12213811328U, 12222199424U, - 12230590336U, 12238977664U, 12247365248U, 12255755392U, 12264143488U, - 12272531584U, 12280920448U, 12289309568U, 12297694592U, 12306086528U, - 12314475392U, 12322865024U, 12331253632U, 12339640448U, 12348029312U, - 12356418944U, 12364805248U, 12373196672U, 12381580928U, 12389969024U, - 12398357632U, 12406750592U, 12415138432U, 12423527552U, 12431916416U, - 12440304512U, 12448692352U, 12457081216U, 12465467776U, 12473859968U, - 12482245504U, 12490636672U, 12499025536U, 12507411584U, 12515801728U, - 12524190592U, 12532577152U, 12540966272U, 12549354368U, 12557743232U, - 12566129536U, 12574523264U, 12582911872U, 12591299456U, 12599688064U, - 12608074624U, 12616463488U, 12624845696U, 12633239936U, 12641631616U, - 12650019968U, 12658407296U, 12666795136U, 12675183232U, 12683574656U, - 12691960192U, 12700350592U, 12708740224U, 12717128576U, 12725515904U, - 12733906816U, 12742295168U, 12750680192U, 12759071872U, 12767460736U, - 12775848832U, 12784236928U, 12792626816U, 12801014656U, 12809404288U, - 12817789312U, 12826181504U, 12834568832U, 12842954624U, 12851345792U, - 12859732352U, 12868122496U, 12876512128U, 12884901248U, 12893289088U, - 12901672832U, 12910067584U, 12918455168U, 12926842496U, 12935232896U, - 12943620736U, 12952009856U, 12960396928U, 12968786816U, 12977176192U, - 12985563776U, 12993951104U, 13002341504U, 13010730368U, 13019115392U, - 13027506304U, 13035895168U, 13044272512U, 13052673152U, 13061062528U, - 13069446272U, 13077838976U, 13086227072U, 13094613632U, 13103000192U, - 13111393664U, 13119782528U, 13128157568U, 13136559232U, 13144945024U, - 13153329536U, 13161724288U, 13170111872U, 13178502784U, 13186884736U, - 13195279744U, 13203667072U, 13212057472U, 13220445824U, 13228832128U, - 13237221248U, 13245610624U, 13254000512U, 13262388352U, 13270777472U, - 13279166336U, 13287553408U, 13295943296U, 13304331904U, 13312719488U, - 13321108096U, 13329494656U, 13337885824U, 13346274944U, 13354663808U, - 13363051136U, 13371439232U, 13379825024U, 13388210816U, 13396605056U, - 13404995456U, 13413380224U, 13421771392U, 13430159744U, 13438546048U, - 13446937216U, 13455326848U, 13463708288U, 13472103808U, 13480492672U, - 13488875648U, 13497269888U, 13505657728U, 13514045312U, 13522435712U, - 13530824576U, 13539210112U, 13547599232U, 13555989376U, 13564379008U, - 13572766336U, 13581154432U, 13589544832U, 13597932928U, 13606320512U, - 13614710656U, 13623097472U, 13631477632U, 13639874944U, 13648264064U, - 13656652928U, 13665041792U, 13673430656U, 13681818496U, 13690207616U, - 13698595712U, 13706982272U, 13715373184U, 13723762048U, 13732150144U, - 13740536704U, 13748926592U, 13757316224U, 13765700992U, 13774090112U, - 13782477952U, 13790869376U, 13799259008U, 13807647872U, 13816036736U, - 13824425344U, 13832814208U, 13841202304U, 13849591424U, 13857978752U, - 13866368896U, 13874754688U, 13883145344U, 13891533184U, 13899919232U, - 13908311168U, 13916692096U, 13925085056U, 13933473152U, 13941866368U, - 13950253696U, 13958643584U, 13967032192U, 13975417216U, 13983807616U, - 13992197504U, 14000582272U, 14008973696U, 14017363072U, 14025752192U, - 14034137984U, 14042528384U, 14050918016U, 14059301504U, 14067691648U, - 14076083584U, 14084470144U, 14092852352U, 14101249664U, 14109635968U, - 14118024832U, 14126407552U, 14134804352U, 14143188608U, 14151577984U, - 14159968384U, 14168357248U, 14176741504U, 14185127296U, 14193521024U, - 14201911424U, 14210301824U, 14218685056U, 14227067264U, 14235467392U, - 14243855488U, 14252243072U, 14260630144U, 14269021568U, 14277409408U, - 14285799296U, 14294187904U, 14302571392U, 14310961792U, 14319353728U, - 14327738752U, 14336130944U, 14344518784U, 14352906368U, 14361296512U, - 14369685376U, 14378071424U, 14386462592U, 14394848128U, 14403230848U, - 14411627392U, 14420013952U, 14428402304U, 14436793472U, 14445181568U, - 14453569664U, 14461959808U, 14470347904U, 14478737024U, 14487122816U, - 14495511424U, 14503901824U, 14512291712U, 14520677504U, 14529064832U, - 14537456768U, 14545845632U, 14554234496U, 14562618496U, 14571011456U, - 14579398784U, 14587789184U, 14596172672U, 14604564608U, 14612953984U, - 14621341312U, 14629724288U, 14638120832U, 14646503296U, 14654897536U, - 14663284864U, 14671675264U, 14680061056U, 14688447616U, 14696835968U, - 14705228416U, 14713616768U, 14722003328U, 14730392192U, 14738784128U, - 14747172736U, 14755561088U, 14763947648U, 14772336512U, 14780725376U, - 14789110144U, 14797499776U, 14805892736U, 14814276992U, 14822670208U, - 14831056256U, 14839444352U, 14847836032U, 14856222848U, 14864612992U, - 14872997504U, 14881388672U, 14889775744U, 14898165376U, 14906553472U, - 14914944896U, 14923329664U, 14931721856U, 14940109696U, 14948497024U, - 14956887424U, 14965276544U, 14973663616U, 14982053248U, 14990439808U, - 14998830976U, 15007216768U, 15015605888U, 15023995264U, 15032385152U, - 15040768384U, 15049154944U, 15057549184U, 15065939072U, 15074328448U, - 15082715008U, 15091104128U, 15099493504U, 15107879296U, 15116269184U, - 15124659584U, 15133042304U, 15141431936U, 15149824384U, 15158214272U, - 15166602368U, 15174991232U, 15183378304U, 15191760512U, 15200154496U, - 15208542592U, 15216931712U, 15225323392U, 15233708416U, 15242098048U, - 15250489216U, 15258875264U, 15267265408U, 15275654528U, 15284043136U, - 15292431488U, 15300819584U, 15309208192U, 15317596544U, 15325986176U, - 15334374784U, 15342763648U, 15351151744U, 15359540608U, 15367929728U, - 15376318336U, 15384706432U, 15393092992U, 15401481856U, 15409869952U, - 15418258816U, 15426649984U, 15435037568U, 15443425664U, 15451815296U, - 15460203392U, 15468589184U, 15476979328U, 15485369216U, 15493755776U, - 15502146944U, 15510534272U, 15518924416U, 15527311232U, 15535699072U, - 15544089472U, 15552478336U, 15560866688U, 15569254528U, 15577642624U, - 15586031488U, 15594419072U, 15602809472U, 15611199104U, 15619586432U, - 15627975296U, 15636364928U, 15644753792U, 15653141888U, 15661529216U, - 15669918848U, 15678305152U, 15686696576U, 15695083136U, 15703474048U, - 15711861632U, 15720251264U, 15728636288U, 15737027456U, 15745417088U, - 15753804928U, 15762194048U, 15770582656U, 15778971008U, 15787358336U, - 15795747712U, 15804132224U, 15812523392U, 15820909696U, 15829300096U, - 15837691264U, 15846071936U, 15854466944U, 15862855808U, 15871244672U, - 15879634816U, 15888020608U, 15896409728U, 15904799104U, 15913185152U, - 15921577088U, 15929966464U, 15938354816U, 15946743424U, 15955129472U, - 15963519872U, 15971907968U, 15980296064U, 15988684928U, 15997073024U, - 16005460864U, 16013851264U, 16022241152U, 16030629248U, 16039012736U, - 16047406976U, 16055794816U, 16064181376U, 16072571264U, 16080957824U, - 16089346688U, 16097737856U, 16106125184U, 16114514816U, 16122904192U, - 16131292544U, 16139678848U, 16148066944U, 16156453504U, 16164839552U, - 16173236096U, 16181623424U, 16190012032U, 16198401152U, 16206790528U, - 16215177344U, 16223567744U, 16231956352U, 16240344704U, 16248731008U, - 16257117824U, 16265504384U, 16273898624U, 16282281856U, 16290668672U, - 16299064192U, 16307449216U, 16315842176U, 16324230016U, 16332613504U, - 16341006464U, 16349394304U, 16357783168U, 16366172288U, 16374561664U, - 16382951296U, 16391337856U, 16399726208U, 16408116352U, 16416505472U, - 16424892032U, 16433282176U, 16441668224U, 16450058624U, 16458448768U, - 16466836864U, 16475224448U, 16483613056U, 16492001408U, 16500391808U, - 16508779648U, 16517166976U, 16525555328U, 16533944192U, 16542330752U, - 16550719616U, 16559110528U, 16567497088U, 16575888512U, 16584274816U, - 16592665472U, 16601051008U, 16609442944U, 16617832064U, 16626218624U, - 16634607488U, 16642996096U, 16651385728U, 16659773824U, 16668163712U, - 16676552576U, 16684938112U, 16693328768U, 16701718144U, 16710095488U, - 16718492288U, 16726883968U, 16735272832U, 16743661184U, 16752049792U, - 16760436608U, 16768827008U, 16777214336U, 16785599104U, 16793992832U, - 16802381696U, 16810768768U, 16819151744U, 16827542656U, 16835934848U, - 16844323712U, 16852711552U, 16861101952U, 16869489536U, 16877876864U, - 16886265728U, 16894653056U, 16903044736U, 16911431296U, 16919821696U, - 16928207488U, 16936592768U, 16944987776U, 16953375616U, 16961763968U, - 16970152832U, 16978540928U, 16986929536U, 16995319168U, 17003704448U, - 17012096896U, 17020481152U, 17028870784U, 17037262208U, 17045649536U, - 17054039936U, 17062426496U, 17070814336U, 17079205504U, 17087592064U, - 17095978112U, 17104369024U, 17112759424U, 17121147776U, 17129536384U, - 17137926016U, 17146314368U, 17154700928U, 17163089792U, 17171480192U, - 17179864192U, 17188256896U, 17196644992U, 17205033856U, 17213423488U, - 17221811072U, 17230198912U, 17238588032U, 17246976896U, 17255360384U, - 17263754624U, 17272143232U, 17280530048U, 17288918912U, 17297309312U, - 17305696384U, 17314085504U, 17322475136U, 17330863744U, 17339252096U, - 17347640192U, 17356026496U, 17364413824U, 17372796544U, 17381190016U, - 17389583488U, 17397972608U, 17406360704U, 17414748544U, 17423135872U, - 17431527296U, 17439915904U, 17448303232U, 17456691584U, 17465081728U, - 17473468288U, 17481857408U, 17490247552U, 17498635904U, 17507022464U, - 17515409024U, 17523801728U, 17532189824U, 17540577664U, 17548966016U, - 17557353344U, 17565741184U, 17574131584U, 17582519168U, 17590907008U, - 17599296128U, 17607687808U, 17616076672U, 17624455808U, 17632852352U, - 17641238656U, 17649630848U, 17658018944U, 17666403968U, 17674794112U, - 17683178368U, 17691573376U, 17699962496U, 17708350592U, 17716739968U, - 17725126528U, 17733517184U, 17741898112U, 17750293888U, 17758673024U, - 17767070336U, 17775458432U, 17783848832U, 17792236928U, 17800625536U, - 17809012352U, 17817402752U, 17825785984U, 17834178944U, 17842563968U, - 17850955648U, 17859344512U, 17867732864U, 17876119424U, 17884511872U, - 17892900224U, 17901287296U, 17909677696U, 17918058112U, 17926451072U, - 17934843776U, 17943230848U, 17951609216U, 17960008576U, 17968397696U, - 17976784256U, 17985175424U, 17993564032U, 18001952128U, 18010339712U, - 18018728576U, 18027116672U, 18035503232U, 18043894144U, 18052283264U, - 18060672128U, 18069056384U, 18077449856U, 18085837184U, 18094225792U, - 18102613376U, 18111004544U, 18119388544U, 18127781248U, 18136170368U, - 18144558976U, 18152947328U, 18161336192U, 18169724288U, 18178108544U, - 18186498944U, 18194886784U, 18203275648U, 18211666048U, 18220048768U, - 18228444544U, 18236833408U, 18245220736U + 1073739904U, 1082130304U, 1090514816U, 1098906752U, 1107293056U, + 1115684224U, 1124070016U, 1132461952U, 1140849536U, 1149232768U, + 1157627776U, 1166013824U, 1174404736U, 1182786944U, 1191180416U, + 1199568512U, 1207958912U, 1216345216U, 1224732032U, 1233124736U, + 1241513344U, 1249902464U, 1258290304U, 1266673792U, 1275067264U, + 1283453312U, 1291844992U, 1300234112U, 1308619904U, 1317010048U, + 1325397376U, 1333787776U, 1342176128U, 1350561664U, 1358954368U, + 1367339392U, 1375731584U, 1384118144U, 1392507008U, 1400897408U, + 1409284736U, 1417673344U, 1426062464U, 1434451072U, 1442839168U, + 1451229056U, 1459615616U, 1468006016U, 1476394112U, 1484782976U, + 1493171584U, 1501559168U, 1509948032U, 1518337664U, 1526726528U, + 1535114624U, 1543503488U, 1551892096U, 1560278656U, 1568669056U, + 1577056384U, 1585446272U, 1593831296U, 1602219392U, 1610610304U, + 1619000192U, 1627386752U, 1635773824U, 1644164224U, 1652555648U, + 1660943488U, 1669332608U, 1677721216U, 1686109312U, 1694497664U, + 1702886272U, 1711274624U, 1719661184U, 1728047744U, 1736434816U, + 1744829056U, 1753218944U, 1761606272U, 1769995904U, 1778382464U, + 1786772864U, 1795157888U, 1803550592U, 1811937664U, 1820327552U, + 1828711552U, 1837102976U, 1845488768U, 1853879936U, 1862269312U, + 1870656896U, 1879048064U, 1887431552U, 1895825024U, 1904212096U, + 1912601216U, 1920988544U, 1929379456U, 1937765504U, 1946156672U, + 1954543232U, 1962932096U, 1971321728U, 1979707264U, 1988093056U, + 1996487552U, 2004874624U, 2013262208U, 2021653888U, 2030039936U, + 2038430848U, 2046819968U, 2055208576U, 2063596672U, 2071981952U, + 2080373632U, 2088762752U, 2097149056U, 2105539712U, 2113928576U, + 2122315136U, 2130700672U, 2139092608U, 2147483264U, 2155872128U, + 2164257664U, 2172642176U, 2181035392U, 2189426048U, 2197814912U, + 2206203008U, 2214587264U, 2222979712U, 2231367808U, 2239758208U, + 2248145024U, 2256527744U, 2264922752U, 2273312128U, 2281701248U, + 2290086272U, 2298476672U, 2306867072U, 2315251072U, 2323639168U, + 2332032128U, 2340420224U, 2348808064U, 2357196416U, 2365580416U, + 2373966976U, 2382363008U, 2390748544U, 2399139968U, 2407530368U, + 2415918976U, 2424307328U, 2432695424U, 2441084288U, 2449472384U, + 2457861248U, 2466247808U, 2474637184U, 2483026816U, 2491414144U, + 2499803776U, 2508191872U, 2516582272U, 2524970368U, 2533359232U, + 2541743488U, 2550134144U, 2558525056U, 2566913408U, 2575301504U, + 2583686528U, 2592073856U, 2600467328U, 2608856192U, 2617240448U, + 2625631616U, 2634022016U, 2642407552U, 2650796416U, 2659188352U, + 2667574912U, 2675965312U, 2684352896U, 2692738688U, 2701130624U, + 2709518464U, 2717907328U, 2726293376U, 2734685056U, 2743073152U, + 2751462016U, 2759851648U, 2768232832U, 2776625536U, 2785017728U, + 2793401984U, 2801794432U, 2810182016U, 2818571648U, 2826959488U, + 2835349376U, 2843734144U, 2852121472U, 2860514432U, 2868900992U, + 2877286784U, 2885676928U, 2894069632U, 2902451584U, 2910843008U, + 2919234688U, 2927622784U, 2936011648U, 2944400768U, 2952789376U, + 2961177728U, 2969565568U, 2977951616U, 2986338944U, 2994731392U, + 3003120256U, 3011508352U, 3019895936U, 3028287104U, 3036675968U, + 3045063808U, 3053452928U, 3061837696U, 3070228352U, 3078615424U, + 3087003776U, 3095394944U, 3103782272U, 3112173184U, 3120562048U, + 3128944768U, 3137339264U, 3145725056U, 3154109312U, 3162505088U, + 3170893184U, 3179280256U, 3187669376U, 3196056704U, 3204445568U, + 3212836736U, 3221224064U, 3229612928U, 3238002304U, 3246391168U, + 3254778496U, 3263165824U, 3271556224U, 3279944576U, 3288332416U, + 3296719232U, 3305110912U, 3313500032U, 3321887104U, 3330273152U, + 3338658944U, 3347053184U, 3355440512U, 3363827072U, 3372220288U, + 3380608384U, 3388997504U, 3397384576U, 3405774208U, 3414163072U, + 3422551936U, 3430937984U, 3439328384U, 3447714176U, 3456104576U, + 3464493952U, 3472883584U, 3481268864U, 3489655168U, 3498048896U, + 3506434432U, 3514826368U, 3523213952U, 3531603584U, 3539987072U, + 3548380288U, 3556763264U, 3565157248U, 3573545344U, 3581934464U, + 3590324096U, 3598712704U, 3607098752U, 3615488384U, 3623877248U, + 3632265856U, 3640646528U, 3649043584U, 3657430144U, 3665821568U, + 3674207872U, 3682597504U, 3690984832U, 3699367808U, 3707764352U, + 3716152448U, 3724541056U, 3732925568U, 3741318016U, 3749706368U, + 3758091136U, 3766481536U, 3774872704U, 3783260032U, 3791650432U, + 3800036224U, 3808427648U, 3816815488U, 3825204608U, 3833592704U, + 3841981568U, 3850370432U, 3858755968U, 3867147904U, 3875536256U, + 3883920512U, 3892313728U, 3900702592U, 3909087872U, 3917478784U, + 3925868416U, 3934256512U, 3942645376U, 3951032192U, 3959422336U, + 3967809152U, 3976200064U, 3984588416U, 3992974976U, 4001363584U, + 4009751168U, 4018141312U, 4026530432U, 4034911616U, 4043308928U, + 4051695488U, 4060084352U, 4068472448U, 4076862848U, 4085249408U, + 4093640576U, 4102028416U, 4110413696U, 4118805632U, 4127194496U, + 4135583104U, 4143971968U, 4152360832U, 4160746112U, 4169135744U, + 4177525888U, 4185912704U, 4194303616U, 4202691968U, 4211076736U, + 4219463552U, 4227855488U, 4236246656U, 4244633728U, 4253022848U, + 4261412224U, 4269799808U, 4278184832U, 4286578048U, 4294962304U, + 4303349632U, 4311743104U, 4320130432U, 4328521088U, 4336909184U, + 4345295488U, 4353687424U, 4362073472U, 4370458496U, 4378852736U, + 4387238528U, 4395630208U, 4404019072U, 4412407424U, 4420790656U, + 4429182848U, 4437571456U, 4445962112U, 4454344064U, 4462738048U, + 4471119232U, 4479516544U, 4487904128U, 4496289664U, 4504682368U, + 4513068416U, 4521459584U, 4529846144U, 4538232704U, 4546619776U, + 4555010176U, 4563402112U, 4571790208U, 4580174464U, 4588567936U, + 4596957056U, 4605344896U, 4613734016U, 4622119808U, 4630511488U, + 4638898816U, 4647287936U, 4655675264U, 4664065664U, 4672451968U, + 4680842624U, 4689231488U, 4697620352U, 4706007424U, 4714397056U, + 4722786176U, 4731173248U, 4739562368U, 4747951744U, 4756340608U, + 4764727936U, 4773114496U, 4781504384U, 4789894784U, 4798283648U, + 4806667648U, 4815059584U, 4823449472U, 4831835776U, 4840226176U, + 4848612224U, 4857003392U, 4865391488U, 4873780096U, 4882169728U, + 4890557312U, 4898946944U, 4907333248U, 4915722368U, 4924110976U, + 4932499328U, 4940889728U, 4949276032U, 4957666432U, 4966054784U, + 4974438016U, 4982831488U, 4991221376U, 4999607168U, 5007998848U, + 5016386432U, 5024763776U, 5033164672U, 5041544576U, 5049941888U, + 5058329728U, 5066717056U, 5075107456U, 5083494272U, 5091883904U, + 5100273536U, 5108662144U, 5117048192U, 5125436032U, 5133827456U, + 5142215296U, 5150605184U, 5158993024U, 5167382144U, 5175769472U, + 5184157568U, 5192543872U, 5200936064U, 5209324928U, 5217711232U, + 5226102656U, 5234490496U, 5242877312U, 5251263872U, 5259654016U, + 5268040832U, 5276434304U, 5284819328U, 5293209728U, 5301598592U, + 5309986688U, 5318374784U, 5326764416U, 5335151488U, 5343542144U, + 5351929472U, 5360319872U, 5368706944U, 5377096576U, 5385484928U, + 5393871232U, 5402263424U, 5410650496U, 5419040384U, 5427426944U, + 5435816576U, 5444205952U, 5452594816U, 5460981376U, 5469367936U, + 5477760896U, 5486148736U, 5494536832U, 5502925952U, 5511315328U, + 5519703424U, 5528089984U, 5536481152U, 5544869504U, 5553256064U, + 5561645696U, 5570032768U, 5578423936U, 5586811264U, 5595193216U, + 5603585408U, 5611972736U, 5620366208U, 5628750464U, 5637143936U, + 5645528192U, 5653921408U, 5662310272U, 5670694784U, 5679082624U, + 5687474048U, 5695864448U, 5704251008U, 5712641408U, 5721030272U, + 5729416832U, 5737806208U, 5746194304U, 5754583936U, 5762969984U, + 5771358592U, 5779748224U, 5788137856U, 5796527488U, 5804911232U, + 5813300608U, 5821692544U, 5830082176U, 5838468992U, 5846855552U, + 5855247488U, 5863636096U, 5872024448U, 5880411008U, 5888799872U, + 5897186432U, 5905576832U, 5913966976U, 5922352768U, 5930744704U, + 5939132288U, 5947522432U, 5955911296U, 5964299392U, 5972688256U, + 5981074304U, 5989465472U, 5997851008U, 6006241408U, 6014627968U, + 6023015552U, 6031408256U, 6039796096U, 6048185216U, 6056574848U, + 6064963456U, 6073351808U, 6081736064U, 6090128768U, 6098517632U, + 6106906496U, 6115289216U, 6123680896U, 6132070016U, 6140459648U, + 6148849024U, 6157237376U, 6165624704U, 6174009728U, 6182403712U, + 6190792064U, 6199176064U, 6207569792U, 6215952256U, 6224345216U, + 6232732544U, 6241124224U, 6249510272U, 6257899136U, 6266287744U, + 6274676864U, 6283065728U, 6291454336U, 6299843456U, 6308232064U, + 6316620928U, 6325006208U, 6333395584U, 6341784704U, 6350174848U, + 6358562176U, 6366951296U, 6375337856U, 6383729536U, 6392119168U, + 6400504192U, 6408895616U, 6417283456U, 6425673344U, 6434059136U, + 6442444672U, 6450837376U, 6459223424U, 6467613056U, 6476004224U, + 6484393088U, 6492781952U, 6501170048U, 6509555072U, 6517947008U, + 6526336384U, 6534725504U, 6543112832U, 6551500672U, 6559888768U, + 6568278656U, 6576662912U, 6585055616U, 6593443456U, 6601834112U, + 6610219648U, 6618610304U, 6626999168U, 6635385472U, 6643777408U, + 6652164224U, 6660552832U, 6668941952U, 6677330048U, 6685719424U, + 6694107776U, 6702493568U, 6710882176U, 6719274112U, 6727662976U, + 6736052096U, 6744437632U, 6752825984U, 6761213824U, 6769604224U, + 6777993856U, 6786383488U, 6794770816U, 6803158144U, 6811549312U, + 6819937664U, 6828326528U, 6836706176U, 6845101696U, 6853491328U, + 6861880448U, 6870269312U, 6878655104U, 6887046272U, 6895433344U, + 6903822208U, 6912212864U, 6920596864U, 6928988288U, 6937377152U, + 6945764992U, 6954149248U, 6962544256U, 6970928768U, 6979317376U, + 6987709312U, 6996093824U, 7004487296U, 7012875392U, 7021258624U, + 7029652352U, 7038038912U, 7046427776U, 7054818944U, 7063207808U, + 7071595136U, 7079980928U, 7088372608U, 7096759424U, 7105149824U, + 7113536896U, 7121928064U, 7130315392U, 7138699648U, 7147092352U, + 7155479168U, 7163865728U, 7172249984U, 7180648064U, 7189036672U, + 7197424768U, 7205810816U, 7214196608U, 7222589824U, 7230975104U, + 7239367552U, 7247755904U, 7256145536U, 7264533376U, 7272921472U, + 7281308032U, 7289694848U, 7298088832U, 7306471808U, 7314864512U, + 7323253888U, 7331643008U, 7340029568U, 7348419712U, 7356808832U, + 7365196672U, 7373585792U, 7381973888U, 7390362752U, 7398750592U, + 7407138944U, 7415528576U, 7423915648U, 7432302208U, 7440690304U, + 7449080192U, 7457472128U, 7465860992U, 7474249088U, 7482635648U, + 7491023744U, 7499412608U, 7507803008U, 7516192384U, 7524579968U, + 7532967296U, 7541358464U, 7549745792U, 7558134656U, 7566524032U, + 7574912896U, 7583300992U, 7591690112U, 7600075136U, 7608466816U, + 7616854912U, 7625244544U, 7633629824U, 7642020992U, 7650410368U, + 7658794112U, 7667187328U, 7675574912U, 7683961984U, 7692349568U, + 7700739712U, 7709130368U, 7717519232U, 7725905536U, 7734295424U, + 7742683264U, 7751069056U, 7759457408U, 7767849088U, 7776238208U, + 7784626816U, 7793014912U, 7801405312U, 7809792128U, 7818179968U, + 7826571136U, 7834957184U, 7843347328U, 7851732352U, 7860124544U, + 7868512384U, 7876902016U, 7885287808U, 7893679744U, 7902067072U, + 7910455936U, 7918844288U, 7927230848U, 7935622784U, 7944009344U, + 7952400256U, 7960786048U, 7969176704U, 7977565312U, 7985953408U, + 7994339968U, 8002730368U, 8011119488U, 8019508096U, 8027896192U, + 8036285056U, 8044674688U, 8053062272U, 8061448832U, 8069838464U, + 8078227328U, 8086616704U, 8095006592U, 8103393664U, 8111783552U, + 8120171392U, 8128560256U, 8136949376U, 8145336704U, 8153726848U, + 8162114944U, 8170503296U, 8178891904U, 8187280768U, 8195669632U, + 8204058496U, 8212444544U, 8220834176U, 8229222272U, 8237612672U, + 8246000768U, 8254389376U, 8262775168U, 8271167104U, 8279553664U, + 8287944064U, 8296333184U, 8304715136U, 8313108352U, 8321497984U, + 8329885568U, 8338274432U, 8346663296U, 8355052928U, 8363441536U, + 8371828352U, 8380217984U, 8388606592U, 8396996224U, 8405384576U, + 8413772672U, 8422161536U, 8430549376U, 8438939008U, 8447326592U, + 8455715456U, 8464104832U, 8472492928U, 8480882048U, 8489270656U, + 8497659776U, 8506045312U, 8514434944U, 8522823808U, 8531208832U, + 8539602304U, 8547990656U, 8556378752U, 8564768384U, 8573154176U, + 8581542784U, 8589933952U, 8598322816U, 8606705024U, 8615099264U, + 8623487872U, 8631876992U, 8640264064U, 8648653952U, 8657040256U, + 8665430656U, 8673820544U, 8682209152U, 8690592128U, 8698977152U, + 8707374464U, 8715763328U, 8724151424U, 8732540032U, 8740928384U, + 8749315712U, 8757704576U, 8766089344U, 8774480768U, 8782871936U, + 8791260032U, 8799645824U, 8808034432U, 8816426368U, 8824812928U, + 8833199488U, 8841591424U, 8849976448U, 8858366336U, 8866757248U, + 8875147136U, 8883532928U, 8891923328U, 8900306816U, 8908700288U, + 8917088384U, 8925478784U, 8933867392U, 8942250368U, 8950644608U, + 8959032704U, 8967420544U, 8975809664U, 8984197504U, 8992584064U, + 9000976256U, 9009362048U, 9017752448U, 9026141312U, 9034530688U, + 9042917504U, 9051307904U, 9059694208U, 9068084864U, 9076471424U, + 9084861824U, 9093250688U, 9101638528U, 9110027648U, 9118416512U, + 9126803584U, 9135188096U, 9143581312U, 9151969664U, 9160356224U, + 9168747136U, 9177134464U, 9185525632U, 9193910144U, 9202302848U, + 9210690688U, 9219079552U, 9227465344U, 9235854464U, 9244244864U, + 9252633472U, 9261021824U, 9269411456U, 9277799296U, 9286188928U, + 9294574208U, 9302965888U, 9311351936U, 9319740032U, 9328131968U, + 9336516736U, 9344907392U, 9353296768U, 9361685888U, 9370074752U, + 9378463616U, 9386849408U, 9395239808U, 9403629184U, 9412016512U, + 9420405376U, 9428795008U, 9437181568U, 9445570688U, 9453960832U, + 9462346624U, 9470738048U, 9479121536U, 9487515008U, 9495903616U, + 9504289664U, 9512678528U, 9521067904U, 9529456256U, 9537843584U, + 9546233728U, 9554621312U, 9563011456U, 9571398784U, 9579788672U, + 9588178304U, 9596567168U, 9604954496U, 9613343104U, 9621732992U, + 9630121856U, 9638508416U, 9646898816U, 9655283584U, 9663675776U, + 9672061312U, 9680449664U, 9688840064U, 9697230464U, 9705617536U, + 9714003584U, 9722393984U, 9730772608U, 9739172224U, 9747561088U, + 9755945344U, 9764338816U, 9772726144U, 9781116544U, 9789503872U, + 9797892992U, 9806282624U, 9814670464U, 9823056512U, 9831439232U, + 9839833984U, 9848224384U, 9856613504U, 9865000576U, 9873391232U, + 9881772416U, 9890162816U, 9898556288U, 9906940544U, 9915333248U, + 9923721088U, 9932108672U, 9940496512U, 9948888448U, 9957276544U, + 9965666176U, 9974048384U, 9982441088U, 9990830464U, 9999219584U, + 10007602816U, 10015996544U, 10024385152U, 10032774016U, 10041163648U, + 10049548928U, 10057940096U, 10066329472U, 10074717824U, 10083105152U, + 10091495296U, 10099878784U, 10108272256U, 10116660608U, 10125049216U, + 10133437312U, 10141825664U, 10150213504U, 10158601088U, 10166991232U, + 10175378816U, 10183766144U, 10192157312U, 10200545408U, 10208935552U, + 10217322112U, 10225712768U, 10234099328U, 10242489472U, 10250876032U, + 10259264896U, 10267656064U, 10276042624U, 10284429184U, 10292820352U, + 10301209472U, 10309598848U, 10317987712U, 10326375296U, 10334763392U, + 10343153536U, 10351541632U, 10359930752U, 10368318592U, 10376707456U, + 10385096576U, 10393484672U, 10401867136U, 10410262144U, 10418647424U, + 10427039104U, 10435425664U, 10443810176U, 10452203648U, 10460589952U, + 10468982144U, 10477369472U, 10485759104U, 10494147712U, 10502533504U, + 10510923392U, 10519313536U, 10527702656U, 10536091264U, 10544478592U, + 10552867712U, 10561255808U, 10569642368U, 10578032768U, 10586423168U, + 10594805632U, 10603200128U, 10611588992U, 10619976064U, 10628361344U, + 10636754048U, 10645143424U, 10653531776U, 10661920384U, 10670307968U, + 10678696832U, 10687086464U, 10695475072U, 10703863168U, 10712246144U, + 10720639616U, 10729026688U, 10737414784U, 10745806208U, 10754190976U, + 10762581376U, 10770971264U, 10779356288U, 10787747456U, 10796135552U, + 10804525184U, 10812915584U, 10821301888U, 10829692288U, 10838078336U, + 10846469248U, 10854858368U, 10863247232U, 10871631488U, 10880023424U, + 10888412032U, 10896799616U, 10905188992U, 10913574016U, 10921964672U, + 10930352768U, 10938742912U, 10947132544U, 10955518592U, 10963909504U, + 10972298368U, 10980687488U, 10989074816U, 10997462912U, 11005851776U, + 11014241152U, 11022627712U, 11031017344U, 11039403904U, 11047793024U, + 11056184704U, 11064570752U, 11072960896U, 11081343872U, 11089737856U, + 11098128256U, 11106514816U, 11114904448U, 11123293568U, 11131680128U, + 11140065152U, 11148458368U, 11156845696U, 11165236864U, 11173624192U, + 11182013824U, 11190402688U, 11198790784U, 11207179136U, 11215568768U, + 11223957376U, 11232345728U, 11240734592U, 11249122688U, 11257511296U, + 11265899648U, 11274285952U, 11282675584U, 11291065472U, 11299452544U, + 11307842432U, 11316231296U, 11324616832U, 11333009024U, 11341395584U, + 11349782656U, 11358172288U, 11366560384U, 11374950016U, 11383339648U, + 11391721856U, 11400117376U, 11408504192U, 11416893568U, 11425283456U, + 11433671552U, 11442061184U, 11450444672U, 11458837888U, 11467226752U, + 11475611776U, 11484003968U, 11492392064U, 11500780672U, 11509169024U, + 11517550976U, 11525944448U, 11534335616U, 11542724224U, 11551111808U, + 11559500672U, 11567890304U, 11576277376U, 11584667008U, 11593056128U, + 11601443456U, 11609830016U, 11618221952U, 11626607488U, 11634995072U, + 11643387776U, 11651775104U, 11660161664U, 11668552576U, 11676940928U, + 11685330304U, 11693718656U, 11702106496U, 11710496128U, 11718882688U, + 11727273088U, 11735660416U, 11744050048U, 11752437376U, 11760824704U, + 11769216128U, 11777604736U, 11785991296U, 11794381952U, 11802770048U, + 11811157888U, 11819548544U, 11827932544U, 11836324736U, 11844713344U, + 11853100928U, 11861486464U, 11869879936U, 11878268032U, 11886656896U, + 11895044992U, 11903433088U, 11911822976U, 11920210816U, 11928600448U, + 11936987264U, 11945375872U, 11953761152U, 11962151296U, 11970543488U, + 11978928512U, 11987320448U, 11995708288U, 12004095104U, 12012486272U, + 12020875136U, 12029255552U, 12037652096U, 12046039168U, 12054429568U, + 12062813824U, 12071206528U, 12079594624U, 12087983744U, 12096371072U, + 12104759936U, 12113147264U, 12121534592U, 12129924992U, 12138314624U, + 12146703232U, 12155091584U, 12163481216U, 12171864704U, 12180255872U, + 12188643968U, 12197034112U, 12205424512U, 12213811328U, 12222199424U, + 12230590336U, 12238977664U, 12247365248U, 12255755392U, 12264143488U, + 12272531584U, 12280920448U, 12289309568U, 12297694592U, 12306086528U, + 12314475392U, 12322865024U, 12331253632U, 12339640448U, 12348029312U, + 12356418944U, 12364805248U, 12373196672U, 12381580928U, 12389969024U, + 12398357632U, 12406750592U, 12415138432U, 12423527552U, 12431916416U, + 12440304512U, 12448692352U, 12457081216U, 12465467776U, 12473859968U, + 12482245504U, 12490636672U, 12499025536U, 12507411584U, 12515801728U, + 12524190592U, 12532577152U, 12540966272U, 12549354368U, 12557743232U, + 12566129536U, 12574523264U, 12582911872U, 12591299456U, 12599688064U, + 12608074624U, 12616463488U, 12624845696U, 12633239936U, 12641631616U, + 12650019968U, 12658407296U, 12666795136U, 12675183232U, 12683574656U, + 12691960192U, 12700350592U, 12708740224U, 12717128576U, 12725515904U, + 12733906816U, 12742295168U, 12750680192U, 12759071872U, 12767460736U, + 12775848832U, 12784236928U, 12792626816U, 12801014656U, 12809404288U, + 12817789312U, 12826181504U, 12834568832U, 12842954624U, 12851345792U, + 12859732352U, 12868122496U, 12876512128U, 12884901248U, 12893289088U, + 12901672832U, 12910067584U, 12918455168U, 12926842496U, 12935232896U, + 12943620736U, 12952009856U, 12960396928U, 12968786816U, 12977176192U, + 12985563776U, 12993951104U, 13002341504U, 13010730368U, 13019115392U, + 13027506304U, 13035895168U, 13044272512U, 13052673152U, 13061062528U, + 13069446272U, 13077838976U, 13086227072U, 13094613632U, 13103000192U, + 13111393664U, 13119782528U, 13128157568U, 13136559232U, 13144945024U, + 13153329536U, 13161724288U, 13170111872U, 13178502784U, 13186884736U, + 13195279744U, 13203667072U, 13212057472U, 13220445824U, 13228832128U, + 13237221248U, 13245610624U, 13254000512U, 13262388352U, 13270777472U, + 13279166336U, 13287553408U, 13295943296U, 13304331904U, 13312719488U, + 13321108096U, 13329494656U, 13337885824U, 13346274944U, 13354663808U, + 13363051136U, 13371439232U, 13379825024U, 13388210816U, 13396605056U, + 13404995456U, 13413380224U, 13421771392U, 13430159744U, 13438546048U, + 13446937216U, 13455326848U, 13463708288U, 13472103808U, 13480492672U, + 13488875648U, 13497269888U, 13505657728U, 13514045312U, 13522435712U, + 13530824576U, 13539210112U, 13547599232U, 13555989376U, 13564379008U, + 13572766336U, 13581154432U, 13589544832U, 13597932928U, 13606320512U, + 13614710656U, 13623097472U, 13631477632U, 13639874944U, 13648264064U, + 13656652928U, 13665041792U, 13673430656U, 13681818496U, 13690207616U, + 13698595712U, 13706982272U, 13715373184U, 13723762048U, 13732150144U, + 13740536704U, 13748926592U, 13757316224U, 13765700992U, 13774090112U, + 13782477952U, 13790869376U, 13799259008U, 13807647872U, 13816036736U, + 13824425344U, 13832814208U, 13841202304U, 13849591424U, 13857978752U, + 13866368896U, 13874754688U, 13883145344U, 13891533184U, 13899919232U, + 13908311168U, 13916692096U, 13925085056U, 13933473152U, 13941866368U, + 13950253696U, 13958643584U, 13967032192U, 13975417216U, 13983807616U, + 13992197504U, 14000582272U, 14008973696U, 14017363072U, 14025752192U, + 14034137984U, 14042528384U, 14050918016U, 14059301504U, 14067691648U, + 14076083584U, 14084470144U, 14092852352U, 14101249664U, 14109635968U, + 14118024832U, 14126407552U, 14134804352U, 14143188608U, 14151577984U, + 14159968384U, 14168357248U, 14176741504U, 14185127296U, 14193521024U, + 14201911424U, 14210301824U, 14218685056U, 14227067264U, 14235467392U, + 14243855488U, 14252243072U, 14260630144U, 14269021568U, 14277409408U, + 14285799296U, 14294187904U, 14302571392U, 14310961792U, 14319353728U, + 14327738752U, 14336130944U, 14344518784U, 14352906368U, 14361296512U, + 14369685376U, 14378071424U, 14386462592U, 14394848128U, 14403230848U, + 14411627392U, 14420013952U, 14428402304U, 14436793472U, 14445181568U, + 14453569664U, 14461959808U, 14470347904U, 14478737024U, 14487122816U, + 14495511424U, 14503901824U, 14512291712U, 14520677504U, 14529064832U, + 14537456768U, 14545845632U, 14554234496U, 14562618496U, 14571011456U, + 14579398784U, 14587789184U, 14596172672U, 14604564608U, 14612953984U, + 14621341312U, 14629724288U, 14638120832U, 14646503296U, 14654897536U, + 14663284864U, 14671675264U, 14680061056U, 14688447616U, 14696835968U, + 14705228416U, 14713616768U, 14722003328U, 14730392192U, 14738784128U, + 14747172736U, 14755561088U, 14763947648U, 14772336512U, 14780725376U, + 14789110144U, 14797499776U, 14805892736U, 14814276992U, 14822670208U, + 14831056256U, 14839444352U, 14847836032U, 14856222848U, 14864612992U, + 14872997504U, 14881388672U, 14889775744U, 14898165376U, 14906553472U, + 14914944896U, 14923329664U, 14931721856U, 14940109696U, 14948497024U, + 14956887424U, 14965276544U, 14973663616U, 14982053248U, 14990439808U, + 14998830976U, 15007216768U, 15015605888U, 15023995264U, 15032385152U, + 15040768384U, 15049154944U, 15057549184U, 15065939072U, 15074328448U, + 15082715008U, 15091104128U, 15099493504U, 15107879296U, 15116269184U, + 15124659584U, 15133042304U, 15141431936U, 15149824384U, 15158214272U, + 15166602368U, 15174991232U, 15183378304U, 15191760512U, 15200154496U, + 15208542592U, 15216931712U, 15225323392U, 15233708416U, 15242098048U, + 15250489216U, 15258875264U, 15267265408U, 15275654528U, 15284043136U, + 15292431488U, 15300819584U, 15309208192U, 15317596544U, 15325986176U, + 15334374784U, 15342763648U, 15351151744U, 15359540608U, 15367929728U, + 15376318336U, 15384706432U, 15393092992U, 15401481856U, 15409869952U, + 15418258816U, 15426649984U, 15435037568U, 15443425664U, 15451815296U, + 15460203392U, 15468589184U, 15476979328U, 15485369216U, 15493755776U, + 15502146944U, 15510534272U, 15518924416U, 15527311232U, 15535699072U, + 15544089472U, 15552478336U, 15560866688U, 15569254528U, 15577642624U, + 15586031488U, 15594419072U, 15602809472U, 15611199104U, 15619586432U, + 15627975296U, 15636364928U, 15644753792U, 15653141888U, 15661529216U, + 15669918848U, 15678305152U, 15686696576U, 15695083136U, 15703474048U, + 15711861632U, 15720251264U, 15728636288U, 15737027456U, 15745417088U, + 15753804928U, 15762194048U, 15770582656U, 15778971008U, 15787358336U, + 15795747712U, 15804132224U, 15812523392U, 15820909696U, 15829300096U, + 15837691264U, 15846071936U, 15854466944U, 15862855808U, 15871244672U, + 15879634816U, 15888020608U, 15896409728U, 15904799104U, 15913185152U, + 15921577088U, 15929966464U, 15938354816U, 15946743424U, 15955129472U, + 15963519872U, 15971907968U, 15980296064U, 15988684928U, 15997073024U, + 16005460864U, 16013851264U, 16022241152U, 16030629248U, 16039012736U, + 16047406976U, 16055794816U, 16064181376U, 16072571264U, 16080957824U, + 16089346688U, 16097737856U, 16106125184U, 16114514816U, 16122904192U, + 16131292544U, 16139678848U, 16148066944U, 16156453504U, 16164839552U, + 16173236096U, 16181623424U, 16190012032U, 16198401152U, 16206790528U, + 16215177344U, 16223567744U, 16231956352U, 16240344704U, 16248731008U, + 16257117824U, 16265504384U, 16273898624U, 16282281856U, 16290668672U, + 16299064192U, 16307449216U, 16315842176U, 16324230016U, 16332613504U, + 16341006464U, 16349394304U, 16357783168U, 16366172288U, 16374561664U, + 16382951296U, 16391337856U, 16399726208U, 16408116352U, 16416505472U, + 16424892032U, 16433282176U, 16441668224U, 16450058624U, 16458448768U, + 16466836864U, 16475224448U, 16483613056U, 16492001408U, 16500391808U, + 16508779648U, 16517166976U, 16525555328U, 16533944192U, 16542330752U, + 16550719616U, 16559110528U, 16567497088U, 16575888512U, 16584274816U, + 16592665472U, 16601051008U, 16609442944U, 16617832064U, 16626218624U, + 16634607488U, 16642996096U, 16651385728U, 16659773824U, 16668163712U, + 16676552576U, 16684938112U, 16693328768U, 16701718144U, 16710095488U, + 16718492288U, 16726883968U, 16735272832U, 16743661184U, 16752049792U, + 16760436608U, 16768827008U, 16777214336U, 16785599104U, 16793992832U, + 16802381696U, 16810768768U, 16819151744U, 16827542656U, 16835934848U, + 16844323712U, 16852711552U, 16861101952U, 16869489536U, 16877876864U, + 16886265728U, 16894653056U, 16903044736U, 16911431296U, 16919821696U, + 16928207488U, 16936592768U, 16944987776U, 16953375616U, 16961763968U, + 16970152832U, 16978540928U, 16986929536U, 16995319168U, 17003704448U, + 17012096896U, 17020481152U, 17028870784U, 17037262208U, 17045649536U, + 17054039936U, 17062426496U, 17070814336U, 17079205504U, 17087592064U, + 17095978112U, 17104369024U, 17112759424U, 17121147776U, 17129536384U, + 17137926016U, 17146314368U, 17154700928U, 17163089792U, 17171480192U, + 17179864192U, 17188256896U, 17196644992U, 17205033856U, 17213423488U, + 17221811072U, 17230198912U, 17238588032U, 17246976896U, 17255360384U, + 17263754624U, 17272143232U, 17280530048U, 17288918912U, 17297309312U, + 17305696384U, 17314085504U, 17322475136U, 17330863744U, 17339252096U, + 17347640192U, 17356026496U, 17364413824U, 17372796544U, 17381190016U, + 17389583488U, 17397972608U, 17406360704U, 17414748544U, 17423135872U, + 17431527296U, 17439915904U, 17448303232U, 17456691584U, 17465081728U, + 17473468288U, 17481857408U, 17490247552U, 17498635904U, 17507022464U, + 17515409024U, 17523801728U, 17532189824U, 17540577664U, 17548966016U, + 17557353344U, 17565741184U, 17574131584U, 17582519168U, 17590907008U, + 17599296128U, 17607687808U, 17616076672U, 17624455808U, 17632852352U, + 17641238656U, 17649630848U, 17658018944U, 17666403968U, 17674794112U, + 17683178368U, 17691573376U, 17699962496U, 17708350592U, 17716739968U, + 17725126528U, 17733517184U, 17741898112U, 17750293888U, 17758673024U, + 17767070336U, 17775458432U, 17783848832U, 17792236928U, 17800625536U, + 17809012352U, 17817402752U, 17825785984U, 17834178944U, 17842563968U, + 17850955648U, 17859344512U, 17867732864U, 17876119424U, 17884511872U, + 17892900224U, 17901287296U, 17909677696U, 17918058112U, 17926451072U, + 17934843776U, 17943230848U, 17951609216U, 17960008576U, 17968397696U, + 17976784256U, 17985175424U, 17993564032U, 18001952128U, 18010339712U, + 18018728576U, 18027116672U, 18035503232U, 18043894144U, 18052283264U, + 18060672128U, 18069056384U, 18077449856U, 18085837184U, 18094225792U, + 18102613376U, 18111004544U, 18119388544U, 18127781248U, 18136170368U, + 18144558976U, 18152947328U, 18161336192U, 18169724288U, 18178108544U, + 18186498944U, 18194886784U, 18203275648U, 18211666048U, 18220048768U, + 18228444544U, 18236833408U, 18245220736U }; @@ -478,335 +478,335 @@ static const uint64_t dag_sizes[2048] = { // Sow[i*HashBytes]; j++]]]][[2]][[1]] const uint64_t cache_sizes[2048] = { - 16776896U, 16907456U, 17039296U, 17170112U, 17301056U, 17432512U, 17563072U, - 17693888U, 17824192U, 17955904U, 18087488U, 18218176U, 18349504U, 18481088U, - 18611392U, 18742336U, 18874304U, 19004224U, 19135936U, 19267264U, 19398208U, - 19529408U, 19660096U, 19791424U, 19922752U, 20053952U, 20184896U, 20315968U, - 20446912U, 20576576U, 20709184U, 20840384U, 20971072U, 21102272U, 21233216U, - 21364544U, 21494848U, 21626816U, 21757376U, 21887552U, 22019392U, 22151104U, - 22281536U, 22412224U, 22543936U, 22675264U, 22806464U, 22935872U, 23068096U, - 23198272U, 23330752U, 23459008U, 23592512U, 23723968U, 23854912U, 23986112U, - 24116672U, 24247616U, 24378688U, 24509504U, 24640832U, 24772544U, 24903488U, - 25034432U, 25165376U, 25296704U, 25427392U, 25558592U, 25690048U, 25820096U, - 25951936U, 26081728U, 26214208U, 26345024U, 26476096U, 26606656U, 26737472U, - 26869184U, 26998208U, 27131584U, 27262528U, 27393728U, 27523904U, 27655744U, - 27786688U, 27917888U, 28049344U, 28179904U, 28311488U, 28441792U, 28573504U, - 28700864U, 28835648U, 28966208U, 29096768U, 29228608U, 29359808U, 29490752U, - 29621824U, 29752256U, 29882816U, 30014912U, 30144448U, 30273728U, 30406976U, - 30538432U, 30670784U, 30799936U, 30932672U, 31063744U, 31195072U, 31325248U, - 31456192U, 31588288U, 31719232U, 31850432U, 31981504U, 32110784U, 32243392U, - 32372672U, 32505664U, 32636608U, 32767808U, 32897344U, 33029824U, 33160768U, - 33289664U, 33423296U, 33554368U, 33683648U, 33816512U, 33947456U, 34076992U, - 34208704U, 34340032U, 34471744U, 34600256U, 34734016U, 34864576U, 34993984U, - 35127104U, 35258176U, 35386688U, 35518528U, 35650624U, 35782336U, 35910976U, - 36044608U, 36175808U, 36305728U, 36436672U, 36568384U, 36699968U, 36830656U, - 36961984U, 37093312U, 37223488U, 37355072U, 37486528U, 37617472U, 37747904U, - 37879232U, 38009792U, 38141888U, 38272448U, 38403392U, 38535104U, 38660672U, - 38795584U, 38925632U, 39059264U, 39190336U, 39320768U, 39452096U, 39581632U, - 39713984U, 39844928U, 39974848U, 40107968U, 40238144U, 40367168U, 40500032U, - 40631744U, 40762816U, 40894144U, 41023552U, 41155904U, 41286208U, 41418304U, - 41547712U, 41680448U, 41811904U, 41942848U, 42073792U, 42204992U, 42334912U, - 42467008U, 42597824U, 42729152U, 42860096U, 42991552U, 43122368U, 43253696U, - 43382848U, 43515712U, 43646912U, 43777088U, 43907648U, 44039104U, 44170432U, - 44302144U, 44433344U, 44564288U, 44694976U, 44825152U, 44956864U, 45088448U, - 45219008U, 45350464U, 45481024U, 45612608U, 45744064U, 45874496U, 46006208U, - 46136768U, 46267712U, 46399424U, 46529344U, 46660672U, 46791488U, 46923328U, - 47053504U, 47185856U, 47316928U, 47447872U, 47579072U, 47710144U, 47839936U, - 47971648U, 48103232U, 48234176U, 48365248U, 48496192U, 48627136U, 48757312U, - 48889664U, 49020736U, 49149248U, 49283008U, 49413824U, 49545152U, 49675712U, - 49807168U, 49938368U, 50069056U, 50200256U, 50331584U, 50462656U, 50593472U, - 50724032U, 50853952U, 50986048U, 51117632U, 51248576U, 51379904U, 51510848U, - 51641792U, 51773248U, 51903296U, 52035136U, 52164032U, 52297664U, 52427968U, - 52557376U, 52690112U, 52821952U, 52952896U, 53081536U, 53213504U, 53344576U, - 53475776U, 53608384U, 53738816U, 53870528U, 54000832U, 54131776U, 54263744U, - 54394688U, 54525248U, 54655936U, 54787904U, 54918592U, 55049152U, 55181248U, - 55312064U, 55442752U, 55574336U, 55705024U, 55836224U, 55967168U, 56097856U, - 56228672U, 56358592U, 56490176U, 56621888U, 56753728U, 56884928U, 57015488U, - 57146816U, 57278272U, 57409216U, 57540416U, 57671104U, 57802432U, 57933632U, - 58064576U, 58195264U, 58326976U, 58457408U, 58588864U, 58720192U, 58849984U, - 58981696U, 59113024U, 59243456U, 59375552U, 59506624U, 59637568U, 59768512U, - 59897792U, 60030016U, 60161984U, 60293056U, 60423872U, 60554432U, 60683968U, - 60817216U, 60948032U, 61079488U, 61209664U, 61341376U, 61471936U, 61602752U, - 61733696U, 61865792U, 61996736U, 62127808U, 62259136U, 62389568U, 62520512U, - 62651584U, 62781632U, 62910784U, 63045056U, 63176128U, 63307072U, 63438656U, - 63569216U, 63700928U, 63831616U, 63960896U, 64093888U, 64225088U, 64355392U, - 64486976U, 64617664U, 64748608U, 64879424U, 65009216U, 65142464U, 65273792U, - 65402816U, 65535424U, 65666752U, 65797696U, 65927744U, 66060224U, 66191296U, - 66321344U, 66453056U, 66584384U, 66715328U, 66846656U, 66977728U, 67108672U, - 67239104U, 67370432U, 67501888U, 67631296U, 67763776U, 67895104U, 68026304U, - 68157248U, 68287936U, 68419264U, 68548288U, 68681408U, 68811968U, 68942912U, - 69074624U, 69205568U, 69337024U, 69467584U, 69599168U, 69729472U, 69861184U, - 69989824U, 70122944U, 70253888U, 70385344U, 70515904U, 70647232U, 70778816U, - 70907968U, 71040832U, 71171648U, 71303104U, 71432512U, 71564992U, 71695168U, - 71826368U, 71958464U, 72089536U, 72219712U, 72350144U, 72482624U, 72613568U, - 72744512U, 72875584U, 73006144U, 73138112U, 73268672U, 73400128U, 73530944U, - 73662272U, 73793344U, 73924544U, 74055104U, 74185792U, 74316992U, 74448832U, - 74579392U, 74710976U, 74841664U, 74972864U, 75102784U, 75233344U, 75364544U, - 75497024U, 75627584U, 75759296U, 75890624U, 76021696U, 76152256U, 76283072U, - 76414144U, 76545856U, 76676672U, 76806976U, 76937792U, 77070016U, 77200832U, - 77331392U, 77462464U, 77593664U, 77725376U, 77856448U, 77987776U, 78118336U, - 78249664U, 78380992U, 78511424U, 78642496U, 78773056U, 78905152U, 79033664U, - 79166656U, 79297472U, 79429568U, 79560512U, 79690816U, 79822784U, 79953472U, - 80084672U, 80214208U, 80346944U, 80477632U, 80608576U, 80740288U, 80870848U, - 81002048U, 81133504U, 81264448U, 81395648U, 81525952U, 81657536U, 81786304U, - 81919808U, 82050112U, 82181312U, 82311616U, 82443968U, 82573376U, 82705984U, - 82835776U, 82967744U, 83096768U, 83230528U, 83359552U, 83491264U, 83622464U, - 83753536U, 83886016U, 84015296U, 84147776U, 84277184U, 84409792U, 84540608U, - 84672064U, 84803008U, 84934336U, 85065152U, 85193792U, 85326784U, 85458496U, - 85589312U, 85721024U, 85851968U, 85982656U, 86112448U, 86244416U, 86370112U, - 86506688U, 86637632U, 86769344U, 86900672U, 87031744U, 87162304U, 87293632U, - 87424576U, 87555392U, 87687104U, 87816896U, 87947968U, 88079168U, 88211264U, - 88341824U, 88473152U, 88603712U, 88735424U, 88862912U, 88996672U, 89128384U, - 89259712U, 89390272U, 89521984U, 89652544U, 89783872U, 89914816U, 90045376U, - 90177088U, 90307904U, 90438848U, 90569152U, 90700096U, 90832832U, 90963776U, - 91093696U, 91223744U, 91356992U, 91486784U, 91618496U, 91749824U, 91880384U, - 92012224U, 92143552U, 92273344U, 92405696U, 92536768U, 92666432U, 92798912U, - 92926016U, 93060544U, 93192128U, 93322816U, 93453632U, 93583936U, 93715136U, - 93845056U, 93977792U, 94109504U, 94240448U, 94371776U, 94501184U, 94632896U, - 94764224U, 94895552U, 95023424U, 95158208U, 95287744U, 95420224U, 95550016U, - 95681216U, 95811904U, 95943872U, 96075328U, 96203584U, 96337856U, 96468544U, - 96599744U, 96731072U, 96860992U, 96992576U, 97124288U, 97254848U, 97385536U, - 97517248U, 97647808U, 97779392U, 97910464U, 98041408U, 98172608U, 98303168U, - 98434496U, 98565568U, 98696768U, 98827328U, 98958784U, 99089728U, 99220928U, - 99352384U, 99482816U, 99614272U, 99745472U, 99876416U, 100007104U, - 100138048U, 100267072U, 100401088U, 100529984U, 100662592U, 100791872U, - 100925248U, 101056064U, 101187392U, 101317952U, 101449408U, 101580608U, - 101711296U, 101841728U, 101973824U, 102104896U, 102235712U, 102366016U, - 102498112U, 102628672U, 102760384U, 102890432U, 103021888U, 103153472U, - 103284032U, 103415744U, 103545152U, 103677248U, 103808576U, 103939648U, - 104070976U, 104201792U, 104332736U, 104462528U, 104594752U, 104725952U, - 104854592U, 104988608U, 105118912U, 105247808U, 105381184U, 105511232U, - 105643072U, 105774784U, 105903296U, 106037056U, 106167872U, 106298944U, - 106429504U, 106561472U, 106691392U, 106822592U, 106954304U, 107085376U, - 107216576U, 107346368U, 107478464U, 107609792U, 107739712U, 107872192U, - 108003136U, 108131392U, 108265408U, 108396224U, 108527168U, 108657344U, - 108789568U, 108920384U, 109049792U, 109182272U, 109312576U, 109444928U, - 109572928U, 109706944U, 109837888U, 109969088U, 110099648U, 110230976U, - 110362432U, 110492992U, 110624704U, 110755264U, 110886208U, 111017408U, - 111148864U, 111279296U, 111410752U, 111541952U, 111673024U, 111803456U, - 111933632U, 112066496U, 112196416U, 112328512U, 112457792U, 112590784U, - 112715968U, 112852672U, 112983616U, 113114944U, 113244224U, 113376448U, - 113505472U, 113639104U, 113770304U, 113901376U, 114031552U, 114163264U, - 114294592U, 114425536U, 114556864U, 114687424U, 114818624U, 114948544U, - 115080512U, 115212224U, 115343296U, 115473472U, 115605184U, 115736128U, - 115867072U, 115997248U, 116128576U, 116260288U, 116391488U, 116522944U, - 116652992U, 116784704U, 116915648U, 117046208U, 117178304U, 117308608U, - 117440192U, 117569728U, 117701824U, 117833024U, 117964096U, 118094656U, - 118225984U, 118357312U, 118489024U, 118617536U, 118749632U, 118882112U, - 119012416U, 119144384U, 119275328U, 119406016U, 119537344U, 119668672U, - 119798464U, 119928896U, 120061376U, 120192832U, 120321728U, 120454336U, - 120584512U, 120716608U, 120848192U, 120979136U, 121109056U, 121241408U, - 121372352U, 121502912U, 121634752U, 121764416U, 121895744U, 122027072U, - 122157632U, 122289088U, 122421184U, 122550592U, 122682944U, 122813888U, - 122945344U, 123075776U, 123207488U, 123338048U, 123468736U, 123600704U, - 123731264U, 123861952U, 123993664U, 124124608U, 124256192U, 124386368U, - 124518208U, 124649024U, 124778048U, 124911296U, 125041088U, 125173696U, - 125303744U, 125432896U, 125566912U, 125696576U, 125829056U, 125958592U, - 126090304U, 126221248U, 126352832U, 126483776U, 126615232U, 126746432U, - 126876608U, 127008704U, 127139392U, 127270336U, 127401152U, 127532224U, - 127663552U, 127794752U, 127925696U, 128055232U, 128188096U, 128319424U, - 128449856U, 128581312U, 128712256U, 128843584U, 128973632U, 129103808U, - 129236288U, 129365696U, 129498944U, 129629888U, 129760832U, 129892288U, - 130023104U, 130154048U, 130283968U, 130416448U, 130547008U, 130678336U, - 130807616U, 130939456U, 131071552U, 131202112U, 131331776U, 131464384U, - 131594048U, 131727296U, 131858368U, 131987392U, 132120256U, 132250816U, - 132382528U, 132513728U, 132644672U, 132774976U, 132905792U, 133038016U, - 133168832U, 133299392U, 133429312U, 133562048U, 133692992U, 133823296U, - 133954624U, 134086336U, 134217152U, 134348608U, 134479808U, 134607296U, - 134741056U, 134872384U, 135002944U, 135134144U, 135265472U, 135396544U, - 135527872U, 135659072U, 135787712U, 135921472U, 136052416U, 136182848U, - 136313792U, 136444864U, 136576448U, 136707904U, 136837952U, 136970048U, - 137099584U, 137232064U, 137363392U, 137494208U, 137625536U, 137755712U, - 137887424U, 138018368U, 138149824U, 138280256U, 138411584U, 138539584U, - 138672832U, 138804928U, 138936128U, 139066688U, 139196864U, 139328704U, - 139460032U, 139590208U, 139721024U, 139852864U, 139984576U, 140115776U, - 140245696U, 140376512U, 140508352U, 140640064U, 140769856U, 140902336U, - 141032768U, 141162688U, 141294016U, 141426496U, 141556544U, 141687488U, - 141819584U, 141949888U, 142080448U, 142212544U, 142342336U, 142474432U, - 142606144U, 142736192U, 142868288U, 142997824U, 143129408U, 143258944U, - 143392448U, 143523136U, 143653696U, 143785024U, 143916992U, 144045632U, - 144177856U, 144309184U, 144440768U, 144570688U, 144701888U, 144832448U, - 144965056U, 145096384U, 145227584U, 145358656U, 145489856U, 145620928U, - 145751488U, 145883072U, 146011456U, 146144704U, 146275264U, 146407232U, - 146538176U, 146668736U, 146800448U, 146931392U, 147062336U, 147193664U, - 147324224U, 147455936U, 147586624U, 147717056U, 147848768U, 147979456U, - 148110784U, 148242368U, 148373312U, 148503232U, 148635584U, 148766144U, - 148897088U, 149028416U, 149159488U, 149290688U, 149420224U, 149551552U, - 149683136U, 149814976U, 149943616U, 150076352U, 150208064U, 150338624U, - 150470464U, 150600256U, 150732224U, 150862784U, 150993088U, 151125952U, - 151254976U, 151388096U, 151519168U, 151649728U, 151778752U, 151911104U, - 152042944U, 152174144U, 152304704U, 152435648U, 152567488U, 152698816U, - 152828992U, 152960576U, 153091648U, 153222976U, 153353792U, 153484096U, - 153616192U, 153747008U, 153878336U, 154008256U, 154139968U, 154270912U, - 154402624U, 154533824U, 154663616U, 154795712U, 154926272U, 155057984U, - 155188928U, 155319872U, 155450816U, 155580608U, 155712064U, 155843392U, - 155971136U, 156106688U, 156237376U, 156367424U, 156499264U, 156630976U, - 156761536U, 156892352U, 157024064U, 157155008U, 157284416U, 157415872U, - 157545536U, 157677248U, 157810496U, 157938112U, 158071744U, 158203328U, - 158334656U, 158464832U, 158596288U, 158727616U, 158858048U, 158988992U, - 159121216U, 159252416U, 159381568U, 159513152U, 159645632U, 159776192U, - 159906496U, 160038464U, 160169536U, 160300352U, 160430656U, 160563008U, - 160693952U, 160822208U, 160956352U, 161086784U, 161217344U, 161349184U, - 161480512U, 161611456U, 161742272U, 161873216U, 162002752U, 162135872U, - 162266432U, 162397888U, 162529216U, 162660032U, 162790976U, 162922048U, - 163052096U, 163184576U, 163314752U, 163446592U, 163577408U, 163707968U, - 163839296U, 163969984U, 164100928U, 164233024U, 164364224U, 164494912U, - 164625856U, 164756672U, 164887616U, 165019072U, 165150016U, 165280064U, - 165412672U, 165543104U, 165674944U, 165805888U, 165936832U, 166067648U, - 166198336U, 166330048U, 166461248U, 166591552U, 166722496U, 166854208U, - 166985408U, 167116736U, 167246656U, 167378368U, 167508416U, 167641024U, - 167771584U, 167903168U, 168034112U, 168164032U, 168295744U, 168427456U, - 168557632U, 168688448U, 168819136U, 168951616U, 169082176U, 169213504U, - 169344832U, 169475648U, 169605952U, 169738048U, 169866304U, 169999552U, - 170131264U, 170262464U, 170393536U, 170524352U, 170655424U, 170782016U, - 170917696U, 171048896U, 171179072U, 171310784U, 171439936U, 171573184U, - 171702976U, 171835072U, 171966272U, 172097216U, 172228288U, 172359232U, - 172489664U, 172621376U, 172747712U, 172883264U, 173014208U, 173144512U, - 173275072U, 173407424U, 173539136U, 173669696U, 173800768U, 173931712U, - 174063424U, 174193472U, 174325696U, 174455744U, 174586816U, 174718912U, - 174849728U, 174977728U, 175109696U, 175242688U, 175374272U, 175504832U, - 175636288U, 175765696U, 175898432U, 176028992U, 176159936U, 176291264U, - 176422592U, 176552512U, 176684864U, 176815424U, 176946496U, 177076544U, - 177209152U, 177340096U, 177470528U, 177600704U, 177731648U, 177864256U, - 177994816U, 178126528U, 178257472U, 178387648U, 178518464U, 178650176U, - 178781888U, 178912064U, 179044288U, 179174848U, 179305024U, 179436736U, - 179568448U, 179698496U, 179830208U, 179960512U, 180092608U, 180223808U, - 180354752U, 180485696U, 180617152U, 180748096U, 180877504U, 181009984U, - 181139264U, 181272512U, 181402688U, 181532608U, 181663168U, 181795136U, - 181926592U, 182057536U, 182190016U, 182320192U, 182451904U, 182582336U, - 182713792U, 182843072U, 182976064U, 183107264U, 183237056U, 183368384U, - 183494848U, 183631424U, 183762752U, 183893824U, 184024768U, 184154816U, - 184286656U, 184417984U, 184548928U, 184680128U, 184810816U, 184941248U, - 185072704U, 185203904U, 185335616U, 185465408U, 185596352U, 185727296U, - 185859904U, 185989696U, 186121664U, 186252992U, 186383552U, 186514112U, - 186645952U, 186777152U, 186907328U, 187037504U, 187170112U, 187301824U, - 187429184U, 187562048U, 187693504U, 187825472U, 187957184U, 188087104U, - 188218304U, 188349376U, 188481344U, 188609728U, 188743616U, 188874304U, - 189005248U, 189136448U, 189265088U, 189396544U, 189528128U, 189660992U, - 189791936U, 189923264U, 190054208U, 190182848U, 190315072U, 190447424U, - 190577984U, 190709312U, 190840768U, 190971328U, 191102656U, 191233472U, - 191364032U, 191495872U, 191626816U, 191758016U, 191888192U, 192020288U, - 192148928U, 192282176U, 192413504U, 192542528U, 192674752U, 192805952U, - 192937792U, 193068608U, 193198912U, 193330496U, 193462208U, 193592384U, - 193723456U, 193854272U, 193985984U, 194116672U, 194247232U, 194379712U, - 194508352U, 194641856U, 194772544U, 194900672U, 195035072U, 195166016U, - 195296704U, 195428032U, 195558592U, 195690304U, 195818176U, 195952576U, - 196083392U, 196214336U, 196345792U, 196476736U, 196607552U, 196739008U, - 196869952U, 197000768U, 197130688U, 197262784U, 197394368U, 197523904U, - 197656384U, 197787584U, 197916608U, 198049472U, 198180544U, 198310208U, - 198442432U, 198573632U, 198705088U, 198834368U, 198967232U, 199097792U, - 199228352U, 199360192U, 199491392U, 199621696U, 199751744U, 199883968U, - 200014016U, 200146624U, 200276672U, 200408128U, 200540096U, 200671168U, - 200801984U, 200933312U, 201062464U, 201194944U, 201326144U, 201457472U, - 201588544U, 201719744U, 201850816U, 201981632U, 202111552U, 202244032U, - 202374464U, 202505152U, 202636352U, 202767808U, 202898368U, 203030336U, - 203159872U, 203292608U, 203423296U, 203553472U, 203685824U, 203816896U, - 203947712U, 204078272U, 204208192U, 204341056U, 204472256U, 204603328U, - 204733888U, 204864448U, 204996544U, 205125568U, 205258304U, 205388864U, - 205517632U, 205650112U, 205782208U, 205913536U, 206044736U, 206176192U, - 206307008U, 206434496U, 206569024U, 206700224U, 206831168U, 206961856U, - 207093056U, 207223616U, 207355328U, 207486784U, 207616832U, 207749056U, - 207879104U, 208010048U, 208141888U, 208273216U, 208404032U, 208534336U, - 208666048U, 208796864U, 208927424U, 209059264U, 209189824U, 209321792U, - 209451584U, 209582656U, 209715136U, 209845568U, 209976896U, 210106432U, - 210239296U, 210370112U, 210501568U, 210630976U, 210763712U, 210894272U, - 211024832U, 211156672U, 211287616U, 211418176U, 211549376U, 211679296U, - 211812032U, 211942592U, 212074432U, 212204864U, 212334016U, 212467648U, - 212597824U, 212727616U, 212860352U, 212991424U, 213120832U, 213253952U, - 213385024U, 213515584U, 213645632U, 213777728U, 213909184U, 214040128U, - 214170688U, 214302656U, 214433728U, 214564544U, 214695232U, 214826048U, - 214956992U, 215089088U, 215219776U, 215350592U, 215482304U, 215613248U, - 215743552U, 215874752U, 216005312U, 216137024U, 216267328U, 216399296U, - 216530752U, 216661696U, 216790592U, 216923968U, 217054528U, 217183168U, - 217316672U, 217448128U, 217579072U, 217709504U, 217838912U, 217972672U, - 218102848U, 218233024U, 218364736U, 218496832U, 218627776U, 218759104U, - 218888896U, 219021248U, 219151936U, 219281728U, 219413056U, 219545024U, - 219675968U, 219807296U, 219938624U, 220069312U, 220200128U, 220331456U, - 220461632U, 220592704U, 220725184U, 220855744U, 220987072U, 221117888U, - 221249216U, 221378368U, 221510336U, 221642048U, 221772736U, 221904832U, - 222031808U, 222166976U, 222297536U, 222428992U, 222559936U, 222690368U, - 222820672U, 222953152U, 223083968U, 223213376U, 223345984U, 223476928U, - 223608512U, 223738688U, 223869376U, 224001472U, 224132672U, 224262848U, - 224394944U, 224524864U, 224657344U, 224788288U, 224919488U, 225050432U, - 225181504U, 225312704U, 225443776U, 225574592U, 225704768U, 225834176U, - 225966784U, 226097216U, 226229824U, 226360384U, 226491712U, 226623424U, - 226754368U, 226885312U, 227015104U, 227147456U, 227278528U, 227409472U, - 227539904U, 227669696U, 227802944U, 227932352U, 228065216U, 228196288U, - 228326464U, 228457792U, 228588736U, 228720064U, 228850112U, 228981056U, - 229113152U, 229243328U, 229375936U, 229505344U, 229636928U, 229769152U, - 229894976U, 230030272U, 230162368U, 230292416U, 230424512U, 230553152U, - 230684864U, 230816704U, 230948416U, 231079616U, 231210944U, 231342016U, - 231472448U, 231603776U, 231733952U, 231866176U, 231996736U, 232127296U, - 232259392U, 232388672U, 232521664U, 232652608U, 232782272U, 232914496U, - 233043904U, 233175616U, 233306816U, 233438528U, 233569984U, 233699776U, - 233830592U, 233962688U, 234092224U, 234221888U, 234353984U, 234485312U, - 234618304U, 234749888U, 234880832U, 235011776U, 235142464U, 235274048U, - 235403456U, 235535936U, 235667392U, 235797568U, 235928768U, 236057152U, - 236190272U, 236322752U, 236453312U, 236583616U, 236715712U, 236846528U, - 236976448U, 237108544U, 237239104U, 237371072U, 237501632U, 237630784U, - 237764416U, 237895232U, 238026688U, 238157632U, 238286912U, 238419392U, - 238548032U, 238681024U, 238812608U, 238941632U, 239075008U, 239206336U, - 239335232U, 239466944U, 239599168U, 239730496U, 239861312U, 239992384U, - 240122816U, 240254656U, 240385856U, 240516928U, 240647872U, 240779072U, - 240909632U, 241040704U, 241171904U, 241302848U, 241433408U, 241565248U, - 241696192U, 241825984U, 241958848U, 242088256U, 242220224U, 242352064U, - 242481856U, 242611648U, 242744896U, 242876224U, 243005632U, 243138496U, - 243268672U, 243400384U, 243531712U, 243662656U, 243793856U, 243924544U, - 244054592U, 244187072U, 244316608U, 244448704U, 244580032U, 244710976U, - 244841536U, 244972864U, 245104448U, 245233984U, 245365312U, 245497792U, - 245628736U, 245759936U, 245889856U, 246021056U, 246152512U, 246284224U, - 246415168U, 246545344U, 246675904U, 246808384U, 246939584U, 247070144U, - 247199552U, 247331648U, 247463872U, 247593536U, 247726016U, 247857088U, - 247987648U, 248116928U, 248249536U, 248380736U, 248512064U, 248643008U, - 248773312U, 248901056U, 249036608U, 249167552U, 249298624U, 249429184U, - 249560512U, 249692096U, 249822784U, 249954112U, 250085312U, 250215488U, - 250345792U, 250478528U, 250608704U, 250739264U, 250870976U, 251002816U, - 251133632U, 251263552U, 251395136U, 251523904U, 251657792U, 251789248U, - 251919424U, 252051392U, 252182464U, 252313408U, 252444224U, 252575552U, - 252706624U, 252836032U, 252968512U, 253099712U, 253227584U, 253361728U, - 253493056U, 253623488U, 253754432U, 253885504U, 254017216U, 254148032U, - 254279488U, 254410432U, 254541376U, 254672576U, 254803264U, 254933824U, - 255065792U, 255196736U, 255326528U, 255458752U, 255589952U, 255721408U, - 255851072U, 255983296U, 256114624U, 256244416U, 256374208U, 256507712U, - 256636096U, 256768832U, 256900544U, 257031616U, 257162176U, 257294272U, - 257424448U, 257555776U, 257686976U, 257818432U, 257949632U, 258079552U, - 258211136U, 258342464U, 258473408U, 258603712U, 258734656U, 258867008U, - 258996544U, 259127744U, 259260224U, 259391296U, 259522112U, 259651904U, - 259784384U, 259915328U, 260045888U, 260175424U, 260308544U, 260438336U, - 260570944U, 260700992U, 260832448U, 260963776U, 261092672U, 261226304U, - 261356864U, 261487936U, 261619648U, 261750592U, 261879872U, 262011968U, - 262143424U, 262274752U, 262404416U, 262537024U, 262667968U, 262799296U, - 262928704U, 263061184U, 263191744U, 263322944U, 263454656U, 263585216U, - 263716672U, 263847872U, 263978944U, 264108608U, 264241088U, 264371648U, - 264501184U, 264632768U, 264764096U, 264895936U, 265024576U, 265158464U, - 265287488U, 265418432U, 265550528U, 265681216U, 265813312U, 265943488U, - 266075968U, 266206144U, 266337728U, 266468032U, 266600384U, 266731072U, - 266862272U, 266993344U, 267124288U, 267255616U, 267386432U, 267516992U, - 267648704U, 267777728U, 267910592U, 268040512U, 268172096U, 268302784U, - 268435264U, 268566208U, 268696256U, 268828096U, 268959296U, 269090368U, - 269221312U, 269352256U, 269482688U, 269614784U, 269745856U, 269876416U, - 270007616U, 270139328U, 270270272U, 270401216U, 270531904U, 270663616U, - 270791744U, 270924736U, 271056832U, 271186112U, 271317184U, 271449536U, - 271580992U, 271711936U, 271843136U, 271973056U, 272105408U, 272236352U, - 272367296U, 272498368U, 272629568U, 272759488U, 272891456U, 273022784U, - 273153856U, 273284672U, 273415616U, 273547072U, 273677632U, 273808448U, - 273937088U, 274071488U, 274200896U, 274332992U, 274463296U, 274595392U, - 274726208U, 274857536U, 274988992U, 275118656U, 275250496U, 275382208U, - 275513024U, 275643968U, 275775296U, 275906368U, 276037184U, 276167872U, - 276297664U, 276429376U, 276560576U, 276692672U, 276822976U, 276955072U, - 277085632U, 277216832U, 277347008U, 277478848U, 277609664U, 277740992U, - 277868608U, 278002624U, 278134336U, 278265536U, 278395328U, 278526784U, - 278657728U, 278789824U, 278921152U, 279052096U, 279182912U, 279313088U, - 279443776U, 279576256U, 279706048U, 279838528U, 279969728U, 280099648U, - 280230976U, 280361408U, 280493632U, 280622528U, 280755392U, 280887104U, - 281018176U, 281147968U, 281278912U, 281411392U, 281542592U, 281673152U, - 281803712U, 281935552U, 282066496U, 282197312U, 282329024U, 282458816U, - 282590272U, 282720832U, 282853184U, 282983744U, 283115072U, 283246144U, - 283377344U, 283508416U, 283639744U, 283770304U, 283901504U, 284032576U, - 284163136U, 284294848U, 284426176U, 284556992U, 284687296U, 284819264U, - 284950208U, 285081536U + 16776896U, 16907456U, 17039296U, 17170112U, 17301056U, 17432512U, 17563072U, + 17693888U, 17824192U, 17955904U, 18087488U, 18218176U, 18349504U, 18481088U, + 18611392U, 18742336U, 18874304U, 19004224U, 19135936U, 19267264U, 19398208U, + 19529408U, 19660096U, 19791424U, 19922752U, 20053952U, 20184896U, 20315968U, + 20446912U, 20576576U, 20709184U, 20840384U, 20971072U, 21102272U, 21233216U, + 21364544U, 21494848U, 21626816U, 21757376U, 21887552U, 22019392U, 22151104U, + 22281536U, 22412224U, 22543936U, 22675264U, 22806464U, 22935872U, 23068096U, + 23198272U, 23330752U, 23459008U, 23592512U, 23723968U, 23854912U, 23986112U, + 24116672U, 24247616U, 24378688U, 24509504U, 24640832U, 24772544U, 24903488U, + 25034432U, 25165376U, 25296704U, 25427392U, 25558592U, 25690048U, 25820096U, + 25951936U, 26081728U, 26214208U, 26345024U, 26476096U, 26606656U, 26737472U, + 26869184U, 26998208U, 27131584U, 27262528U, 27393728U, 27523904U, 27655744U, + 27786688U, 27917888U, 28049344U, 28179904U, 28311488U, 28441792U, 28573504U, + 28700864U, 28835648U, 28966208U, 29096768U, 29228608U, 29359808U, 29490752U, + 29621824U, 29752256U, 29882816U, 30014912U, 30144448U, 30273728U, 30406976U, + 30538432U, 30670784U, 30799936U, 30932672U, 31063744U, 31195072U, 31325248U, + 31456192U, 31588288U, 31719232U, 31850432U, 31981504U, 32110784U, 32243392U, + 32372672U, 32505664U, 32636608U, 32767808U, 32897344U, 33029824U, 33160768U, + 33289664U, 33423296U, 33554368U, 33683648U, 33816512U, 33947456U, 34076992U, + 34208704U, 34340032U, 34471744U, 34600256U, 34734016U, 34864576U, 34993984U, + 35127104U, 35258176U, 35386688U, 35518528U, 35650624U, 35782336U, 35910976U, + 36044608U, 36175808U, 36305728U, 36436672U, 36568384U, 36699968U, 36830656U, + 36961984U, 37093312U, 37223488U, 37355072U, 37486528U, 37617472U, 37747904U, + 37879232U, 38009792U, 38141888U, 38272448U, 38403392U, 38535104U, 38660672U, + 38795584U, 38925632U, 39059264U, 39190336U, 39320768U, 39452096U, 39581632U, + 39713984U, 39844928U, 39974848U, 40107968U, 40238144U, 40367168U, 40500032U, + 40631744U, 40762816U, 40894144U, 41023552U, 41155904U, 41286208U, 41418304U, + 41547712U, 41680448U, 41811904U, 41942848U, 42073792U, 42204992U, 42334912U, + 42467008U, 42597824U, 42729152U, 42860096U, 42991552U, 43122368U, 43253696U, + 43382848U, 43515712U, 43646912U, 43777088U, 43907648U, 44039104U, 44170432U, + 44302144U, 44433344U, 44564288U, 44694976U, 44825152U, 44956864U, 45088448U, + 45219008U, 45350464U, 45481024U, 45612608U, 45744064U, 45874496U, 46006208U, + 46136768U, 46267712U, 46399424U, 46529344U, 46660672U, 46791488U, 46923328U, + 47053504U, 47185856U, 47316928U, 47447872U, 47579072U, 47710144U, 47839936U, + 47971648U, 48103232U, 48234176U, 48365248U, 48496192U, 48627136U, 48757312U, + 48889664U, 49020736U, 49149248U, 49283008U, 49413824U, 49545152U, 49675712U, + 49807168U, 49938368U, 50069056U, 50200256U, 50331584U, 50462656U, 50593472U, + 50724032U, 50853952U, 50986048U, 51117632U, 51248576U, 51379904U, 51510848U, + 51641792U, 51773248U, 51903296U, 52035136U, 52164032U, 52297664U, 52427968U, + 52557376U, 52690112U, 52821952U, 52952896U, 53081536U, 53213504U, 53344576U, + 53475776U, 53608384U, 53738816U, 53870528U, 54000832U, 54131776U, 54263744U, + 54394688U, 54525248U, 54655936U, 54787904U, 54918592U, 55049152U, 55181248U, + 55312064U, 55442752U, 55574336U, 55705024U, 55836224U, 55967168U, 56097856U, + 56228672U, 56358592U, 56490176U, 56621888U, 56753728U, 56884928U, 57015488U, + 57146816U, 57278272U, 57409216U, 57540416U, 57671104U, 57802432U, 57933632U, + 58064576U, 58195264U, 58326976U, 58457408U, 58588864U, 58720192U, 58849984U, + 58981696U, 59113024U, 59243456U, 59375552U, 59506624U, 59637568U, 59768512U, + 59897792U, 60030016U, 60161984U, 60293056U, 60423872U, 60554432U, 60683968U, + 60817216U, 60948032U, 61079488U, 61209664U, 61341376U, 61471936U, 61602752U, + 61733696U, 61865792U, 61996736U, 62127808U, 62259136U, 62389568U, 62520512U, + 62651584U, 62781632U, 62910784U, 63045056U, 63176128U, 63307072U, 63438656U, + 63569216U, 63700928U, 63831616U, 63960896U, 64093888U, 64225088U, 64355392U, + 64486976U, 64617664U, 64748608U, 64879424U, 65009216U, 65142464U, 65273792U, + 65402816U, 65535424U, 65666752U, 65797696U, 65927744U, 66060224U, 66191296U, + 66321344U, 66453056U, 66584384U, 66715328U, 66846656U, 66977728U, 67108672U, + 67239104U, 67370432U, 67501888U, 67631296U, 67763776U, 67895104U, 68026304U, + 68157248U, 68287936U, 68419264U, 68548288U, 68681408U, 68811968U, 68942912U, + 69074624U, 69205568U, 69337024U, 69467584U, 69599168U, 69729472U, 69861184U, + 69989824U, 70122944U, 70253888U, 70385344U, 70515904U, 70647232U, 70778816U, + 70907968U, 71040832U, 71171648U, 71303104U, 71432512U, 71564992U, 71695168U, + 71826368U, 71958464U, 72089536U, 72219712U, 72350144U, 72482624U, 72613568U, + 72744512U, 72875584U, 73006144U, 73138112U, 73268672U, 73400128U, 73530944U, + 73662272U, 73793344U, 73924544U, 74055104U, 74185792U, 74316992U, 74448832U, + 74579392U, 74710976U, 74841664U, 74972864U, 75102784U, 75233344U, 75364544U, + 75497024U, 75627584U, 75759296U, 75890624U, 76021696U, 76152256U, 76283072U, + 76414144U, 76545856U, 76676672U, 76806976U, 76937792U, 77070016U, 77200832U, + 77331392U, 77462464U, 77593664U, 77725376U, 77856448U, 77987776U, 78118336U, + 78249664U, 78380992U, 78511424U, 78642496U, 78773056U, 78905152U, 79033664U, + 79166656U, 79297472U, 79429568U, 79560512U, 79690816U, 79822784U, 79953472U, + 80084672U, 80214208U, 80346944U, 80477632U, 80608576U, 80740288U, 80870848U, + 81002048U, 81133504U, 81264448U, 81395648U, 81525952U, 81657536U, 81786304U, + 81919808U, 82050112U, 82181312U, 82311616U, 82443968U, 82573376U, 82705984U, + 82835776U, 82967744U, 83096768U, 83230528U, 83359552U, 83491264U, 83622464U, + 83753536U, 83886016U, 84015296U, 84147776U, 84277184U, 84409792U, 84540608U, + 84672064U, 84803008U, 84934336U, 85065152U, 85193792U, 85326784U, 85458496U, + 85589312U, 85721024U, 85851968U, 85982656U, 86112448U, 86244416U, 86370112U, + 86506688U, 86637632U, 86769344U, 86900672U, 87031744U, 87162304U, 87293632U, + 87424576U, 87555392U, 87687104U, 87816896U, 87947968U, 88079168U, 88211264U, + 88341824U, 88473152U, 88603712U, 88735424U, 88862912U, 88996672U, 89128384U, + 89259712U, 89390272U, 89521984U, 89652544U, 89783872U, 89914816U, 90045376U, + 90177088U, 90307904U, 90438848U, 90569152U, 90700096U, 90832832U, 90963776U, + 91093696U, 91223744U, 91356992U, 91486784U, 91618496U, 91749824U, 91880384U, + 92012224U, 92143552U, 92273344U, 92405696U, 92536768U, 92666432U, 92798912U, + 92926016U, 93060544U, 93192128U, 93322816U, 93453632U, 93583936U, 93715136U, + 93845056U, 93977792U, 94109504U, 94240448U, 94371776U, 94501184U, 94632896U, + 94764224U, 94895552U, 95023424U, 95158208U, 95287744U, 95420224U, 95550016U, + 95681216U, 95811904U, 95943872U, 96075328U, 96203584U, 96337856U, 96468544U, + 96599744U, 96731072U, 96860992U, 96992576U, 97124288U, 97254848U, 97385536U, + 97517248U, 97647808U, 97779392U, 97910464U, 98041408U, 98172608U, 98303168U, + 98434496U, 98565568U, 98696768U, 98827328U, 98958784U, 99089728U, 99220928U, + 99352384U, 99482816U, 99614272U, 99745472U, 99876416U, 100007104U, + 100138048U, 100267072U, 100401088U, 100529984U, 100662592U, 100791872U, + 100925248U, 101056064U, 101187392U, 101317952U, 101449408U, 101580608U, + 101711296U, 101841728U, 101973824U, 102104896U, 102235712U, 102366016U, + 102498112U, 102628672U, 102760384U, 102890432U, 103021888U, 103153472U, + 103284032U, 103415744U, 103545152U, 103677248U, 103808576U, 103939648U, + 104070976U, 104201792U, 104332736U, 104462528U, 104594752U, 104725952U, + 104854592U, 104988608U, 105118912U, 105247808U, 105381184U, 105511232U, + 105643072U, 105774784U, 105903296U, 106037056U, 106167872U, 106298944U, + 106429504U, 106561472U, 106691392U, 106822592U, 106954304U, 107085376U, + 107216576U, 107346368U, 107478464U, 107609792U, 107739712U, 107872192U, + 108003136U, 108131392U, 108265408U, 108396224U, 108527168U, 108657344U, + 108789568U, 108920384U, 109049792U, 109182272U, 109312576U, 109444928U, + 109572928U, 109706944U, 109837888U, 109969088U, 110099648U, 110230976U, + 110362432U, 110492992U, 110624704U, 110755264U, 110886208U, 111017408U, + 111148864U, 111279296U, 111410752U, 111541952U, 111673024U, 111803456U, + 111933632U, 112066496U, 112196416U, 112328512U, 112457792U, 112590784U, + 112715968U, 112852672U, 112983616U, 113114944U, 113244224U, 113376448U, + 113505472U, 113639104U, 113770304U, 113901376U, 114031552U, 114163264U, + 114294592U, 114425536U, 114556864U, 114687424U, 114818624U, 114948544U, + 115080512U, 115212224U, 115343296U, 115473472U, 115605184U, 115736128U, + 115867072U, 115997248U, 116128576U, 116260288U, 116391488U, 116522944U, + 116652992U, 116784704U, 116915648U, 117046208U, 117178304U, 117308608U, + 117440192U, 117569728U, 117701824U, 117833024U, 117964096U, 118094656U, + 118225984U, 118357312U, 118489024U, 118617536U, 118749632U, 118882112U, + 119012416U, 119144384U, 119275328U, 119406016U, 119537344U, 119668672U, + 119798464U, 119928896U, 120061376U, 120192832U, 120321728U, 120454336U, + 120584512U, 120716608U, 120848192U, 120979136U, 121109056U, 121241408U, + 121372352U, 121502912U, 121634752U, 121764416U, 121895744U, 122027072U, + 122157632U, 122289088U, 122421184U, 122550592U, 122682944U, 122813888U, + 122945344U, 123075776U, 123207488U, 123338048U, 123468736U, 123600704U, + 123731264U, 123861952U, 123993664U, 124124608U, 124256192U, 124386368U, + 124518208U, 124649024U, 124778048U, 124911296U, 125041088U, 125173696U, + 125303744U, 125432896U, 125566912U, 125696576U, 125829056U, 125958592U, + 126090304U, 126221248U, 126352832U, 126483776U, 126615232U, 126746432U, + 126876608U, 127008704U, 127139392U, 127270336U, 127401152U, 127532224U, + 127663552U, 127794752U, 127925696U, 128055232U, 128188096U, 128319424U, + 128449856U, 128581312U, 128712256U, 128843584U, 128973632U, 129103808U, + 129236288U, 129365696U, 129498944U, 129629888U, 129760832U, 129892288U, + 130023104U, 130154048U, 130283968U, 130416448U, 130547008U, 130678336U, + 130807616U, 130939456U, 131071552U, 131202112U, 131331776U, 131464384U, + 131594048U, 131727296U, 131858368U, 131987392U, 132120256U, 132250816U, + 132382528U, 132513728U, 132644672U, 132774976U, 132905792U, 133038016U, + 133168832U, 133299392U, 133429312U, 133562048U, 133692992U, 133823296U, + 133954624U, 134086336U, 134217152U, 134348608U, 134479808U, 134607296U, + 134741056U, 134872384U, 135002944U, 135134144U, 135265472U, 135396544U, + 135527872U, 135659072U, 135787712U, 135921472U, 136052416U, 136182848U, + 136313792U, 136444864U, 136576448U, 136707904U, 136837952U, 136970048U, + 137099584U, 137232064U, 137363392U, 137494208U, 137625536U, 137755712U, + 137887424U, 138018368U, 138149824U, 138280256U, 138411584U, 138539584U, + 138672832U, 138804928U, 138936128U, 139066688U, 139196864U, 139328704U, + 139460032U, 139590208U, 139721024U, 139852864U, 139984576U, 140115776U, + 140245696U, 140376512U, 140508352U, 140640064U, 140769856U, 140902336U, + 141032768U, 141162688U, 141294016U, 141426496U, 141556544U, 141687488U, + 141819584U, 141949888U, 142080448U, 142212544U, 142342336U, 142474432U, + 142606144U, 142736192U, 142868288U, 142997824U, 143129408U, 143258944U, + 143392448U, 143523136U, 143653696U, 143785024U, 143916992U, 144045632U, + 144177856U, 144309184U, 144440768U, 144570688U, 144701888U, 144832448U, + 144965056U, 145096384U, 145227584U, 145358656U, 145489856U, 145620928U, + 145751488U, 145883072U, 146011456U, 146144704U, 146275264U, 146407232U, + 146538176U, 146668736U, 146800448U, 146931392U, 147062336U, 147193664U, + 147324224U, 147455936U, 147586624U, 147717056U, 147848768U, 147979456U, + 148110784U, 148242368U, 148373312U, 148503232U, 148635584U, 148766144U, + 148897088U, 149028416U, 149159488U, 149290688U, 149420224U, 149551552U, + 149683136U, 149814976U, 149943616U, 150076352U, 150208064U, 150338624U, + 150470464U, 150600256U, 150732224U, 150862784U, 150993088U, 151125952U, + 151254976U, 151388096U, 151519168U, 151649728U, 151778752U, 151911104U, + 152042944U, 152174144U, 152304704U, 152435648U, 152567488U, 152698816U, + 152828992U, 152960576U, 153091648U, 153222976U, 153353792U, 153484096U, + 153616192U, 153747008U, 153878336U, 154008256U, 154139968U, 154270912U, + 154402624U, 154533824U, 154663616U, 154795712U, 154926272U, 155057984U, + 155188928U, 155319872U, 155450816U, 155580608U, 155712064U, 155843392U, + 155971136U, 156106688U, 156237376U, 156367424U, 156499264U, 156630976U, + 156761536U, 156892352U, 157024064U, 157155008U, 157284416U, 157415872U, + 157545536U, 157677248U, 157810496U, 157938112U, 158071744U, 158203328U, + 158334656U, 158464832U, 158596288U, 158727616U, 158858048U, 158988992U, + 159121216U, 159252416U, 159381568U, 159513152U, 159645632U, 159776192U, + 159906496U, 160038464U, 160169536U, 160300352U, 160430656U, 160563008U, + 160693952U, 160822208U, 160956352U, 161086784U, 161217344U, 161349184U, + 161480512U, 161611456U, 161742272U, 161873216U, 162002752U, 162135872U, + 162266432U, 162397888U, 162529216U, 162660032U, 162790976U, 162922048U, + 163052096U, 163184576U, 163314752U, 163446592U, 163577408U, 163707968U, + 163839296U, 163969984U, 164100928U, 164233024U, 164364224U, 164494912U, + 164625856U, 164756672U, 164887616U, 165019072U, 165150016U, 165280064U, + 165412672U, 165543104U, 165674944U, 165805888U, 165936832U, 166067648U, + 166198336U, 166330048U, 166461248U, 166591552U, 166722496U, 166854208U, + 166985408U, 167116736U, 167246656U, 167378368U, 167508416U, 167641024U, + 167771584U, 167903168U, 168034112U, 168164032U, 168295744U, 168427456U, + 168557632U, 168688448U, 168819136U, 168951616U, 169082176U, 169213504U, + 169344832U, 169475648U, 169605952U, 169738048U, 169866304U, 169999552U, + 170131264U, 170262464U, 170393536U, 170524352U, 170655424U, 170782016U, + 170917696U, 171048896U, 171179072U, 171310784U, 171439936U, 171573184U, + 171702976U, 171835072U, 171966272U, 172097216U, 172228288U, 172359232U, + 172489664U, 172621376U, 172747712U, 172883264U, 173014208U, 173144512U, + 173275072U, 173407424U, 173539136U, 173669696U, 173800768U, 173931712U, + 174063424U, 174193472U, 174325696U, 174455744U, 174586816U, 174718912U, + 174849728U, 174977728U, 175109696U, 175242688U, 175374272U, 175504832U, + 175636288U, 175765696U, 175898432U, 176028992U, 176159936U, 176291264U, + 176422592U, 176552512U, 176684864U, 176815424U, 176946496U, 177076544U, + 177209152U, 177340096U, 177470528U, 177600704U, 177731648U, 177864256U, + 177994816U, 178126528U, 178257472U, 178387648U, 178518464U, 178650176U, + 178781888U, 178912064U, 179044288U, 179174848U, 179305024U, 179436736U, + 179568448U, 179698496U, 179830208U, 179960512U, 180092608U, 180223808U, + 180354752U, 180485696U, 180617152U, 180748096U, 180877504U, 181009984U, + 181139264U, 181272512U, 181402688U, 181532608U, 181663168U, 181795136U, + 181926592U, 182057536U, 182190016U, 182320192U, 182451904U, 182582336U, + 182713792U, 182843072U, 182976064U, 183107264U, 183237056U, 183368384U, + 183494848U, 183631424U, 183762752U, 183893824U, 184024768U, 184154816U, + 184286656U, 184417984U, 184548928U, 184680128U, 184810816U, 184941248U, + 185072704U, 185203904U, 185335616U, 185465408U, 185596352U, 185727296U, + 185859904U, 185989696U, 186121664U, 186252992U, 186383552U, 186514112U, + 186645952U, 186777152U, 186907328U, 187037504U, 187170112U, 187301824U, + 187429184U, 187562048U, 187693504U, 187825472U, 187957184U, 188087104U, + 188218304U, 188349376U, 188481344U, 188609728U, 188743616U, 188874304U, + 189005248U, 189136448U, 189265088U, 189396544U, 189528128U, 189660992U, + 189791936U, 189923264U, 190054208U, 190182848U, 190315072U, 190447424U, + 190577984U, 190709312U, 190840768U, 190971328U, 191102656U, 191233472U, + 191364032U, 191495872U, 191626816U, 191758016U, 191888192U, 192020288U, + 192148928U, 192282176U, 192413504U, 192542528U, 192674752U, 192805952U, + 192937792U, 193068608U, 193198912U, 193330496U, 193462208U, 193592384U, + 193723456U, 193854272U, 193985984U, 194116672U, 194247232U, 194379712U, + 194508352U, 194641856U, 194772544U, 194900672U, 195035072U, 195166016U, + 195296704U, 195428032U, 195558592U, 195690304U, 195818176U, 195952576U, + 196083392U, 196214336U, 196345792U, 196476736U, 196607552U, 196739008U, + 196869952U, 197000768U, 197130688U, 197262784U, 197394368U, 197523904U, + 197656384U, 197787584U, 197916608U, 198049472U, 198180544U, 198310208U, + 198442432U, 198573632U, 198705088U, 198834368U, 198967232U, 199097792U, + 199228352U, 199360192U, 199491392U, 199621696U, 199751744U, 199883968U, + 200014016U, 200146624U, 200276672U, 200408128U, 200540096U, 200671168U, + 200801984U, 200933312U, 201062464U, 201194944U, 201326144U, 201457472U, + 201588544U, 201719744U, 201850816U, 201981632U, 202111552U, 202244032U, + 202374464U, 202505152U, 202636352U, 202767808U, 202898368U, 203030336U, + 203159872U, 203292608U, 203423296U, 203553472U, 203685824U, 203816896U, + 203947712U, 204078272U, 204208192U, 204341056U, 204472256U, 204603328U, + 204733888U, 204864448U, 204996544U, 205125568U, 205258304U, 205388864U, + 205517632U, 205650112U, 205782208U, 205913536U, 206044736U, 206176192U, + 206307008U, 206434496U, 206569024U, 206700224U, 206831168U, 206961856U, + 207093056U, 207223616U, 207355328U, 207486784U, 207616832U, 207749056U, + 207879104U, 208010048U, 208141888U, 208273216U, 208404032U, 208534336U, + 208666048U, 208796864U, 208927424U, 209059264U, 209189824U, 209321792U, + 209451584U, 209582656U, 209715136U, 209845568U, 209976896U, 210106432U, + 210239296U, 210370112U, 210501568U, 210630976U, 210763712U, 210894272U, + 211024832U, 211156672U, 211287616U, 211418176U, 211549376U, 211679296U, + 211812032U, 211942592U, 212074432U, 212204864U, 212334016U, 212467648U, + 212597824U, 212727616U, 212860352U, 212991424U, 213120832U, 213253952U, + 213385024U, 213515584U, 213645632U, 213777728U, 213909184U, 214040128U, + 214170688U, 214302656U, 214433728U, 214564544U, 214695232U, 214826048U, + 214956992U, 215089088U, 215219776U, 215350592U, 215482304U, 215613248U, + 215743552U, 215874752U, 216005312U, 216137024U, 216267328U, 216399296U, + 216530752U, 216661696U, 216790592U, 216923968U, 217054528U, 217183168U, + 217316672U, 217448128U, 217579072U, 217709504U, 217838912U, 217972672U, + 218102848U, 218233024U, 218364736U, 218496832U, 218627776U, 218759104U, + 218888896U, 219021248U, 219151936U, 219281728U, 219413056U, 219545024U, + 219675968U, 219807296U, 219938624U, 220069312U, 220200128U, 220331456U, + 220461632U, 220592704U, 220725184U, 220855744U, 220987072U, 221117888U, + 221249216U, 221378368U, 221510336U, 221642048U, 221772736U, 221904832U, + 222031808U, 222166976U, 222297536U, 222428992U, 222559936U, 222690368U, + 222820672U, 222953152U, 223083968U, 223213376U, 223345984U, 223476928U, + 223608512U, 223738688U, 223869376U, 224001472U, 224132672U, 224262848U, + 224394944U, 224524864U, 224657344U, 224788288U, 224919488U, 225050432U, + 225181504U, 225312704U, 225443776U, 225574592U, 225704768U, 225834176U, + 225966784U, 226097216U, 226229824U, 226360384U, 226491712U, 226623424U, + 226754368U, 226885312U, 227015104U, 227147456U, 227278528U, 227409472U, + 227539904U, 227669696U, 227802944U, 227932352U, 228065216U, 228196288U, + 228326464U, 228457792U, 228588736U, 228720064U, 228850112U, 228981056U, + 229113152U, 229243328U, 229375936U, 229505344U, 229636928U, 229769152U, + 229894976U, 230030272U, 230162368U, 230292416U, 230424512U, 230553152U, + 230684864U, 230816704U, 230948416U, 231079616U, 231210944U, 231342016U, + 231472448U, 231603776U, 231733952U, 231866176U, 231996736U, 232127296U, + 232259392U, 232388672U, 232521664U, 232652608U, 232782272U, 232914496U, + 233043904U, 233175616U, 233306816U, 233438528U, 233569984U, 233699776U, + 233830592U, 233962688U, 234092224U, 234221888U, 234353984U, 234485312U, + 234618304U, 234749888U, 234880832U, 235011776U, 235142464U, 235274048U, + 235403456U, 235535936U, 235667392U, 235797568U, 235928768U, 236057152U, + 236190272U, 236322752U, 236453312U, 236583616U, 236715712U, 236846528U, + 236976448U, 237108544U, 237239104U, 237371072U, 237501632U, 237630784U, + 237764416U, 237895232U, 238026688U, 238157632U, 238286912U, 238419392U, + 238548032U, 238681024U, 238812608U, 238941632U, 239075008U, 239206336U, + 239335232U, 239466944U, 239599168U, 239730496U, 239861312U, 239992384U, + 240122816U, 240254656U, 240385856U, 240516928U, 240647872U, 240779072U, + 240909632U, 241040704U, 241171904U, 241302848U, 241433408U, 241565248U, + 241696192U, 241825984U, 241958848U, 242088256U, 242220224U, 242352064U, + 242481856U, 242611648U, 242744896U, 242876224U, 243005632U, 243138496U, + 243268672U, 243400384U, 243531712U, 243662656U, 243793856U, 243924544U, + 244054592U, 244187072U, 244316608U, 244448704U, 244580032U, 244710976U, + 244841536U, 244972864U, 245104448U, 245233984U, 245365312U, 245497792U, + 245628736U, 245759936U, 245889856U, 246021056U, 246152512U, 246284224U, + 246415168U, 246545344U, 246675904U, 246808384U, 246939584U, 247070144U, + 247199552U, 247331648U, 247463872U, 247593536U, 247726016U, 247857088U, + 247987648U, 248116928U, 248249536U, 248380736U, 248512064U, 248643008U, + 248773312U, 248901056U, 249036608U, 249167552U, 249298624U, 249429184U, + 249560512U, 249692096U, 249822784U, 249954112U, 250085312U, 250215488U, + 250345792U, 250478528U, 250608704U, 250739264U, 250870976U, 251002816U, + 251133632U, 251263552U, 251395136U, 251523904U, 251657792U, 251789248U, + 251919424U, 252051392U, 252182464U, 252313408U, 252444224U, 252575552U, + 252706624U, 252836032U, 252968512U, 253099712U, 253227584U, 253361728U, + 253493056U, 253623488U, 253754432U, 253885504U, 254017216U, 254148032U, + 254279488U, 254410432U, 254541376U, 254672576U, 254803264U, 254933824U, + 255065792U, 255196736U, 255326528U, 255458752U, 255589952U, 255721408U, + 255851072U, 255983296U, 256114624U, 256244416U, 256374208U, 256507712U, + 256636096U, 256768832U, 256900544U, 257031616U, 257162176U, 257294272U, + 257424448U, 257555776U, 257686976U, 257818432U, 257949632U, 258079552U, + 258211136U, 258342464U, 258473408U, 258603712U, 258734656U, 258867008U, + 258996544U, 259127744U, 259260224U, 259391296U, 259522112U, 259651904U, + 259784384U, 259915328U, 260045888U, 260175424U, 260308544U, 260438336U, + 260570944U, 260700992U, 260832448U, 260963776U, 261092672U, 261226304U, + 261356864U, 261487936U, 261619648U, 261750592U, 261879872U, 262011968U, + 262143424U, 262274752U, 262404416U, 262537024U, 262667968U, 262799296U, + 262928704U, 263061184U, 263191744U, 263322944U, 263454656U, 263585216U, + 263716672U, 263847872U, 263978944U, 264108608U, 264241088U, 264371648U, + 264501184U, 264632768U, 264764096U, 264895936U, 265024576U, 265158464U, + 265287488U, 265418432U, 265550528U, 265681216U, 265813312U, 265943488U, + 266075968U, 266206144U, 266337728U, 266468032U, 266600384U, 266731072U, + 266862272U, 266993344U, 267124288U, 267255616U, 267386432U, 267516992U, + 267648704U, 267777728U, 267910592U, 268040512U, 268172096U, 268302784U, + 268435264U, 268566208U, 268696256U, 268828096U, 268959296U, 269090368U, + 269221312U, 269352256U, 269482688U, 269614784U, 269745856U, 269876416U, + 270007616U, 270139328U, 270270272U, 270401216U, 270531904U, 270663616U, + 270791744U, 270924736U, 271056832U, 271186112U, 271317184U, 271449536U, + 271580992U, 271711936U, 271843136U, 271973056U, 272105408U, 272236352U, + 272367296U, 272498368U, 272629568U, 272759488U, 272891456U, 273022784U, + 273153856U, 273284672U, 273415616U, 273547072U, 273677632U, 273808448U, + 273937088U, 274071488U, 274200896U, 274332992U, 274463296U, 274595392U, + 274726208U, 274857536U, 274988992U, 275118656U, 275250496U, 275382208U, + 275513024U, 275643968U, 275775296U, 275906368U, 276037184U, 276167872U, + 276297664U, 276429376U, 276560576U, 276692672U, 276822976U, 276955072U, + 277085632U, 277216832U, 277347008U, 277478848U, 277609664U, 277740992U, + 277868608U, 278002624U, 278134336U, 278265536U, 278395328U, 278526784U, + 278657728U, 278789824U, 278921152U, 279052096U, 279182912U, 279313088U, + 279443776U, 279576256U, 279706048U, 279838528U, 279969728U, 280099648U, + 280230976U, 280361408U, 280493632U, 280622528U, 280755392U, 280887104U, + 281018176U, 281147968U, 281278912U, 281411392U, 281542592U, 281673152U, + 281803712U, 281935552U, 282066496U, 282197312U, 282329024U, 282458816U, + 282590272U, 282720832U, 282853184U, 282983744U, 283115072U, 283246144U, + 283377344U, 283508416U, 283639744U, 283770304U, 283901504U, 284032576U, + 284163136U, 284294848U, 284426176U, 284556992U, 284687296U, 284819264U, + 284950208U, 285081536U }; #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/libethash/endian.h b/libethash/endian.h index 9ca842e47..0ee402d9a 100644 --- a/libethash/endian.h +++ b/libethash/endian.h @@ -3,38 +3,6 @@ #include #include "compiler.h" -static const uint8_t BitReverseTable256[] = - { - 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, - 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, - 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, - 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, - 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, - 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, - 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, - 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, - 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, - 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, - 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, - 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, - 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, - 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, - 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, - 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF - }; - -static inline uint32_t bitfn_swap32(uint32_t a) { - return (BitReverseTable256[a & 0xff] << 24) | - (BitReverseTable256[(a >> 8) & 0xff] << 16) | - (BitReverseTable256[(a >> 16) & 0xff] << 8) | - (BitReverseTable256[(a >> 24) & 0xff]); -} - -static inline uint64_t bitfn_swap64(uint64_t a) { - return ((uint64_t) bitfn_swap32((uint32_t) (a >> 32))) | - (((uint64_t) bitfn_swap32((uint32_t) a)) << 32); -} - #if defined(__MINGW32__) || defined(_WIN32) # define LITTLE_ENDIAN 1234 # define BYTE_ORDER LITTLE_ENDIAN @@ -53,22 +21,52 @@ static inline uint64_t bitfn_swap64(uint64_t a) { # define BIG_ENDIAN 1234 # define BYTE_ORDER BIG_ENDIAN #else - # include +#endif +#if defined(_WIN32) +#include +#define ethash_swap_u32(input_) _byteswap_ulong(input_) +#define ethash_swap_u64(input_) _byteswap_uint64(input_) +#elif defined(__APPLE__) +#include +#define ethash_swap_u32(input_) OSSwapInt32(input_) +#define ethash_swap_u64(input_) OSSwapInt64(input_) +#else // posix +#include +#define ethash_swap_u32(input_) __bswap_32(input_) +#define ethash_swap_u64(input_) __bswap_64(input_) #endif #if LITTLE_ENDIAN == BYTE_ORDER -#define fix_endian32(x) (x) -#define fix_endian64(x) (x) +#define fix_endian32(dst_ ,src_) dst_ = src_ +#define fix_endian32_same(val_) +#define fix_endian64(dst_, src_) dst_ = src_ +#define fix_endian64_same(val_) +#define fix_endian_arr32(arr_, size_) +#define fix_endian_arr64(arr_, size_) #elif BIG_ENDIAN == BYTE_ORDER -#define fix_endian32(x) bitfn_swap32(x) -#define fix_endian64(x) bitfn_swap64(x) +#define fix_endian32(dst_, src_) dst_ = ethash_swap_u32(src_) +#define fix_endian32_same(val_) val_ = ethash_swap_u32(val_) +#define fix_endian64(dst_, src_) dst_ = ethash_swap_u64(src_ +#define fix_endian64_same(val_) val_ = ethash_swap_u64(val_) +#define fix_endian_arr32(arr_, size_) \ + do { \ + for (unsigned i_ = 0; i_ < (size_), ++i_) { \ + arr_[i_] = ethash_swap_u32(arr_[i_]); \ + } \ + while (0) +#define fix_endian_arr64(arr_, size_) \ + do { \ + for (unsigned i_ = 0; i_ < (size_), ++i_) { \ + arr_[i_] = ethash_swap_u64(arr_[i_]); \ + } \ + while (0) \ #else # error "endian not supported" -#endif // BYTE_ORDER \ No newline at end of file +#endif // BYTE_ORDER diff --git a/libethash/ethash.h b/libethash/ethash.h index bc62a29cc..0c6a1f9e9 100644 --- a/libethash/ethash.h +++ b/libethash/ethash.h @@ -24,7 +24,6 @@ #include #include #include -#include #include "compiler.h" #define ETHASH_REVISION 23 @@ -38,101 +37,110 @@ #define ETHASH_DATASET_PARENTS 256 #define ETHASH_CACHE_ROUNDS 3 #define ETHASH_ACCESSES 64 +#define ETHASH_DAG_MAGIC_NUM_SIZE 8 +#define ETHASH_DAG_MAGIC_NUM 0xFEE1DEADBADDCAFE #ifdef __cplusplus extern "C" { #endif -typedef struct ethash_params { - uint64_t full_size; // Size of full data set (in bytes, multiple of mix size (128)). - uint64_t cache_size; // Size of compute cache (in bytes, multiple of node size (64)). -} ethash_params; +/// Type of a seedhash/blockhash e.t.c. +typedef struct ethash_h256 { uint8_t b[32]; } ethash_h256_t; -typedef struct ethash_return_value { - uint8_t result[32]; - uint8_t mix_hash[32]; -} ethash_return_value; - -uint64_t ethash_get_datasize(const uint32_t block_number); -uint64_t ethash_get_cachesize(const uint32_t block_number); - -// initialize the parameters -static inline void ethash_params_init(ethash_params *params, const uint32_t block_number) { - params->full_size = ethash_get_datasize(block_number); - params->cache_size = ethash_get_cachesize(block_number); -} - -/*********************************** - * OLD API ************************* - *********************************** - ******************** (deprecated) * - ***********************************/ +// convenience macro to statically initialize an h256_t +// usage: +// ethash_h256_t a = ethash_h256_static_init(1, 2, 3, ... ) +// have to provide all 32 values. If you don't provide all the rest +// will simply be unitialized (not guranteed to be 0) +#define ethash_h256_static_init(...) \ + { {__VA_ARGS__} } -void ethash_get_seedhash(uint8_t seedhash[32], const uint32_t block_number); -void ethash_mkcache(void *cache, ethash_params const *params, const uint8_t seed[32]); -void ethash_light(ethash_return_value *ret, void const *cache, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce); -void ethash_compute_full_data(void *mem, ethash_params const *params, void const *cache); -void ethash_full(ethash_return_value *ret, void const *full_mem, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce); +struct ethash_light; +typedef struct ethash_light* ethash_light_t; +struct ethash_full; +typedef struct ethash_full* ethash_full_t; +typedef int(*ethash_callback_t)(unsigned); -/*********************************** - * NEW API ************************* - ***********************************/ - -// TODO: compute params and seed in ethash_new_light; it should take only block_number -// TODO: store params in ethash_light_t/ethash_full_t to avoid having to repass into compute/new_full - -typedef uint8_t const ethash_seedhash_t[32]; - -typedef void const* ethash_light_t; -static inline ethash_light_t ethash_new_light(ethash_params const* params, ethash_seedhash_t seed) { - void* ret = malloc((size_t)params->cache_size); - ethash_mkcache(ret, params, seed); - return ret; -} -static inline void ethash_compute_light(ethash_return_value *ret, ethash_light_t light, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce) { - ethash_light(ret, light, params, header_hash, nonce); -} -static inline void ethash_delete_light(ethash_light_t light) { - free((void*)light); -} - -typedef void const* ethash_full_t; -static inline ethash_full_t ethash_new_full(ethash_params const* params, ethash_light_t light) { - void* ret = malloc((size_t)params->full_size); - ethash_compute_full_data(ret, params, light); - return ret; -} -static inline void ethash_prep_full(void *full, ethash_params const *params, void const *cache) { - ethash_compute_full_data(full, params, cache); -} -static inline void ethash_compute_full(ethash_return_value *ret, void const *full, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce) { - ethash_full(ret, full, params, header_hash, nonce); -} - -/// @brief Compare two s256-bit big-endian values. -/// @returns 1 if @a a is less than or equal to @a b, 0 otherwise. -/// Both parameters are 256-bit big-endian values. -static inline int ethash_leq_be256(const uint8_t a[32], const uint8_t b[32]) { - // Boundary is big endian - for (int i = 0; i < 32; i++) { - if (a[i] == b[i]) - continue; - return a[i] < b[i]; - } - return 1; -} - -/// Perofrms a cursory check on the validity of the nonce. -/// @returns 1 if the nonce may possibly be valid for the given header_hash & boundary. -/// @p boundary equivalent to 2 ^ 256 / block_difficulty, represented as a 256-bit big-endian. -int ethash_preliminary_check_boundary( - const uint8_t header_hash[32], - const uint64_t nonce, - const uint8_t mix_hash[32], - const uint8_t boundary[32]); - -#define ethash_quick_check_difficulty ethash_preliminary_check_boundary -#define ethash_check_difficulty ethash_leq_be256 +typedef struct ethash_return_value { + ethash_h256_t result; + ethash_h256_t mix_hash; + bool success; +} ethash_return_value_t; + +/** + * Allocate and initialize a new ethash_light handler + * + * @param block_number The block number for which to create the handler + * @return Newly allocated ethash_light handler or NULL in case of + * ERRNOMEM or invalid parameters used for @ref ethash_compute_cache_nodes() + */ +ethash_light_t ethash_light_new(uint64_t block_number); +/** + * Frees a previously allocated ethash_light handler + * @param light The light handler to free + */ +void ethash_light_delete(ethash_light_t light); +/** + * Calculate the light client data + * + * @param light The light client handler + * @param header_hash The header hash to pack into the mix + * @param nonce The nonce to pack into the mix + * @return an object of ethash_return_value_t holding the return values + */ +ethash_return_value_t ethash_light_compute( + ethash_light_t light, + ethash_h256_t const header_hash, + uint64_t nonce +); + +/** + * Allocate and initialize a new ethash_full handler + * + * @param light The light handler containing the cache. + * @param callback A callback function with signature of @ref ethash_callback_t + * It accepts an unsigned with which a progress of DAG calculation + * can be displayed. If all goes well the callback should return 0. + * If a non-zero value is returned then DAG generation will stop. + * Be advised. A progress value of 100 means that DAG creation is + * almost complete and that this function will soon return succesfully. + * It does not mean that the function has already had a succesfull return. + * @return Newly allocated ethash_full handler or NULL in case of + * ERRNOMEM or invalid parameters used for @ref ethash_compute_full_data() + */ +ethash_full_t ethash_full_new(ethash_light_t light, ethash_callback_t callback); + +/** + * Frees a previously allocated ethash_full handler + * @param full The light handler to free + */ +void ethash_full_delete(ethash_full_t full); +/** + * Calculate the full client data + * + * @param full The full client handler + * @param header_hash The header hash to pack into the mix + * @param nonce The nonce to pack into the mix + * @return An object of ethash_return_value to hold the return value + */ +ethash_return_value_t ethash_full_compute( + ethash_full_t full, + ethash_h256_t const header_hash, + uint64_t nonce +); +/** + * Get a pointer to the full DAG data + */ +void const* ethash_full_dag(ethash_full_t full); +/** + * Get the size of the DAG data + */ +uint64_t ethash_full_dag_size(ethash_full_t full); + +/** + * Calculate the seedhash for a given block number + */ +ethash_h256_t ethash_get_seedhash(uint64_t block_number); #ifdef __cplusplus } diff --git a/libethash/fnv.h b/libethash/fnv.h index edabeaae2..d23c4e247 100644 --- a/libethash/fnv.h +++ b/libethash/fnv.h @@ -29,10 +29,11 @@ extern "C" { #define FNV_PRIME 0x01000193 -static inline uint32_t fnv_hash(const uint32_t x, const uint32_t y) { - return x*FNV_PRIME ^ y; +static inline uint32_t fnv_hash(uint32_t const x, uint32_t const y) +{ + return x * FNV_PRIME ^ y; } #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/libethash/internal.c b/libethash/internal.c index 130ca13c3..e881e0c7b 100644 --- a/libethash/internal.c +++ b/libethash/internal.c @@ -8,11 +8,11 @@ ethash 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 + 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 . + along with cpp-ethereum. If not, see . */ /** @file internal.c * @author Tim Hughes @@ -23,11 +23,15 @@ #include #include #include +#include +#include +#include "mmap.h" #include "ethash.h" #include "fnv.h" #include "endian.h" #include "internal.h" #include "data_sizes.h" +#include "io.h" #ifdef WITH_CRYPTOPP @@ -37,264 +41,456 @@ #include "sha3.h" #endif // WITH_CRYPTOPP -uint64_t ethash_get_datasize(const uint32_t block_number) { - assert(block_number / ETHASH_EPOCH_LENGTH < 2048); - return dag_sizes[block_number / ETHASH_EPOCH_LENGTH]; +uint64_t ethash_get_datasize(uint64_t const block_number) +{ + assert(block_number / ETHASH_EPOCH_LENGTH < 2048); + return dag_sizes[block_number / ETHASH_EPOCH_LENGTH]; } -uint64_t ethash_get_cachesize(const uint32_t block_number) { - assert(block_number / ETHASH_EPOCH_LENGTH < 2048); - return cache_sizes[block_number / ETHASH_EPOCH_LENGTH]; +uint64_t ethash_get_cachesize(uint64_t const block_number) +{ + assert(block_number / ETHASH_EPOCH_LENGTH < 2048); + return cache_sizes[block_number / ETHASH_EPOCH_LENGTH]; } // Follows Sergio's "STRICT MEMORY HARD HASHING FUNCTIONS" (2014) // https://bitslog.files.wordpress.com/2013/12/memohash-v0-3.pdf // SeqMemoHash(s, R, N) -void static ethash_compute_cache_nodes( - node *const nodes, - ethash_params const *params, - const uint8_t seed[32]) { - assert((params->cache_size % sizeof(node)) == 0); - uint32_t const num_nodes = (uint32_t) (params->cache_size / sizeof(node)); - - SHA3_512(nodes[0].bytes, seed, 32); - - for (unsigned i = 1; i != num_nodes; ++i) { - SHA3_512(nodes[i].bytes, nodes[i - 1].bytes, 64); - } - - for (unsigned j = 0; j != ETHASH_CACHE_ROUNDS; j++) { - for (unsigned i = 0; i != num_nodes; i++) { - uint32_t const idx = nodes[i].words[0] % num_nodes; - node data; - data = nodes[(num_nodes - 1 + i) % num_nodes]; - for (unsigned w = 0; w != NODE_WORDS; ++w) { - data.words[w] ^= nodes[idx].words[w]; - } - SHA3_512(nodes[i].bytes, data.bytes, sizeof(data)); - } - } - - // now perform endian conversion -#if BYTE_ORDER != LITTLE_ENDIAN - for (unsigned w = 0; w != (num_nodes*NODE_WORDS); ++w) - { - nodes->words[w] = fix_endian32(nodes->words[w]); - } -#endif -} - -void ethash_mkcache( - void *cache, - ethash_params const *params, - const uint8_t seed[32]) { - node *nodes = (node *) cache; - ethash_compute_cache_nodes(nodes, params, seed); +bool static ethash_compute_cache_nodes( + node* const nodes, + uint64_t cache_size, + ethash_h256_t const* seed +) +{ + if (cache_size % sizeof(node) != 0) { + return false; + } + uint32_t const num_nodes = (uint32_t) (cache_size / sizeof(node)); + + SHA3_512(nodes[0].bytes, (uint8_t*)seed, 32); + + for (uint32_t i = 1; i != num_nodes; ++i) { + SHA3_512(nodes[i].bytes, nodes[i - 1].bytes, 64); + } + + for (uint32_t j = 0; j != ETHASH_CACHE_ROUNDS; j++) { + for (uint32_t i = 0; i != num_nodes; i++) { + uint32_t const idx = nodes[i].words[0] % num_nodes; + node data; + data = nodes[(num_nodes - 1 + i) % num_nodes]; + for (uint32_t w = 0; w != NODE_WORDS; ++w) { + data.words[w] ^= nodes[idx].words[w]; + } + SHA3_512(nodes[i].bytes, data.bytes, sizeof(data)); + } + } + + // now perform endian conversion + fix_endian_arr32(nodes->words, num_nodes * NODE_WORDS); + return true; } void ethash_calculate_dag_item( - node *const ret, - const unsigned node_index, - const struct ethash_params *params, - const void *cache) { - - uint32_t num_parent_nodes = (uint32_t) (params->cache_size / sizeof(node)); - node const *cache_nodes = (node const *) cache; - node const *init = &cache_nodes[node_index % num_parent_nodes]; - - memcpy(ret, init, sizeof(node)); - ret->words[0] ^= node_index; - SHA3_512(ret->bytes, ret->bytes, sizeof(node)); - + node* const ret, + uint32_t node_index, + ethash_light_t const light +) +{ + uint32_t num_parent_nodes = (uint32_t) (light->cache_size / sizeof(node)); + node const* cache_nodes = (node const *) light->cache; + node const* init = &cache_nodes[node_index % num_parent_nodes]; + memcpy(ret, init, sizeof(node)); + ret->words[0] ^= node_index; + SHA3_512(ret->bytes, ret->bytes, sizeof(node)); #if defined(_M_X64) && ENABLE_SSE - __m128i const fnv_prime = _mm_set1_epi32(FNV_PRIME); - __m128i xmm0 = ret->xmm[0]; - __m128i xmm1 = ret->xmm[1]; - __m128i xmm2 = ret->xmm[2]; - __m128i xmm3 = ret->xmm[3]; + __m128i const fnv_prime = _mm_set1_epi32(FNV_PRIME); + __m128i xmm0 = ret->xmm[0]; + __m128i xmm1 = ret->xmm[1]; + __m128i xmm2 = ret->xmm[2]; + __m128i xmm3 = ret->xmm[3]; #endif - for (unsigned i = 0; i != ETHASH_DATASET_PARENTS; ++i) { - uint32_t parent_index = ((node_index ^ i) * FNV_PRIME ^ ret->words[i % NODE_WORDS]) % num_parent_nodes; - node const *parent = &cache_nodes[parent_index]; + for (uint32_t i = 0; i != ETHASH_DATASET_PARENTS; ++i) { + uint32_t parent_index = fnv_hash(node_index ^ i, ret->words[i % NODE_WORDS]) % num_parent_nodes; + node const *parent = &cache_nodes[parent_index]; #if defined(_M_X64) && ENABLE_SSE - { - xmm0 = _mm_mullo_epi32(xmm0, fnv_prime); - xmm1 = _mm_mullo_epi32(xmm1, fnv_prime); - xmm2 = _mm_mullo_epi32(xmm2, fnv_prime); - xmm3 = _mm_mullo_epi32(xmm3, fnv_prime); - xmm0 = _mm_xor_si128(xmm0, parent->xmm[0]); - xmm1 = _mm_xor_si128(xmm1, parent->xmm[1]); - xmm2 = _mm_xor_si128(xmm2, parent->xmm[2]); - xmm3 = _mm_xor_si128(xmm3, parent->xmm[3]); - - // have to write to ret as values are used to compute index - ret->xmm[0] = xmm0; - ret->xmm[1] = xmm1; - ret->xmm[2] = xmm2; - ret->xmm[3] = xmm3; - } - #else - { - for (unsigned w = 0; w != NODE_WORDS; ++w) { - ret->words[w] = fnv_hash(ret->words[w], parent->words[w]); - } - } + { + xmm0 = _mm_mullo_epi32(xmm0, fnv_prime); + xmm1 = _mm_mullo_epi32(xmm1, fnv_prime); + xmm2 = _mm_mullo_epi32(xmm2, fnv_prime); + xmm3 = _mm_mullo_epi32(xmm3, fnv_prime); + xmm0 = _mm_xor_si128(xmm0, parent->xmm[0]); + xmm1 = _mm_xor_si128(xmm1, parent->xmm[1]); + xmm2 = _mm_xor_si128(xmm2, parent->xmm[2]); + xmm3 = _mm_xor_si128(xmm3, parent->xmm[3]); + + // have to write to ret as values are used to compute index + ret->xmm[0] = xmm0; + ret->xmm[1] = xmm1; + ret->xmm[2] = xmm2; + ret->xmm[3] = xmm3; + } + #else + { + for (unsigned w = 0; w != NODE_WORDS; ++w) { + ret->words[w] = fnv_hash(ret->words[w], parent->words[w]); + } + } #endif - } - - SHA3_512(ret->bytes, ret->bytes, sizeof(node)); + } + SHA3_512(ret->bytes, ret->bytes, sizeof(node)); } -void ethash_compute_full_data( - void *mem, - ethash_params const *params, - void const *cache) { - assert((params->full_size % (sizeof(uint32_t) * MIX_WORDS)) == 0); - assert((params->full_size % sizeof(node)) == 0); - node *full_nodes = mem; - - // now compute full nodes - for (unsigned n = 0; n != (params->full_size / sizeof(node)); ++n) { - ethash_calculate_dag_item(&(full_nodes[n]), n, params, cache); - } +bool ethash_compute_full_data( + void* mem, + uint64_t full_size, + ethash_light_t const light, + ethash_callback_t callback +) +{ + if (full_size % (sizeof(uint32_t) * MIX_WORDS) != 0 || + (full_size % sizeof(node)) != 0) { + return false; + } + uint32_t const max_n = (uint32_t)(full_size / sizeof(node)); + node* full_nodes = mem; + double const progress_change = 1.0f / max_n; + double progress = 0.0f; + // now compute full nodes + for (uint32_t n = 0; n != max_n; ++n) { + if (callback && + n % (max_n / 100) == 0 && + callback((unsigned int)(ceil(progress * 100.0f))) != 0) { + + return false; + } + progress += progress_change; + ethash_calculate_dag_item(&(full_nodes[n]), n, light); + } + return true; } -static void ethash_hash( - ethash_return_value *ret, - node const *full_nodes, - void const *cache, - ethash_params const *params, - const uint8_t header_hash[32], - const uint64_t nonce) { - - assert((params->full_size % MIX_WORDS) == 0); +static bool ethash_hash( + ethash_return_value_t* ret, + node const* full_nodes, + ethash_light_t const light, + uint64_t full_size, + ethash_h256_t const header_hash, + uint64_t const nonce +) +{ + if (full_size % MIX_WORDS != 0) { + return false; + } + + // pack hash and nonce together into first 40 bytes of s_mix + assert(sizeof(node) * 8 == 512); + node s_mix[MIX_NODES + 1]; + memcpy(s_mix[0].bytes, &header_hash, 32); + fix_endian64(s_mix[0].double_words[4], nonce); + + // compute sha3-512 hash and replicate across mix + SHA3_512(s_mix->bytes, s_mix->bytes, 40); + fix_endian_arr32(s_mix[0].words, 16); + + node* const mix = s_mix + 1; + for (uint32_t w = 0; w != MIX_WORDS; ++w) { + mix->words[w] = s_mix[0].words[w % NODE_WORDS]; + } + + unsigned const page_size = sizeof(uint32_t) * MIX_WORDS; + unsigned const num_full_pages = (unsigned) (full_size / page_size); + + for (unsigned i = 0; i != ETHASH_ACCESSES; ++i) { + uint32_t const index = fnv_hash(s_mix->words[0] ^ i, mix->words[i % MIX_WORDS]) % num_full_pages; + + for (unsigned n = 0; n != MIX_NODES; ++n) { + node const* dag_node; + if (full_nodes) { + dag_node = &full_nodes[MIX_NODES * index + n]; + } else { + node tmp_node; + ethash_calculate_dag_item(&tmp_node, index * MIX_NODES + n, light); + dag_node = &tmp_node; + } - // pack hash and nonce together into first 40 bytes of s_mix - assert(sizeof(node) * 8 == 512); - node s_mix[MIX_NODES + 1]; - memcpy(s_mix[0].bytes, header_hash, 32); - -#if BYTE_ORDER != LITTLE_ENDIAN - s_mix[0].double_words[4] = fix_endian64(nonce); -#else - s_mix[0].double_words[4] = nonce; +#if defined(_M_X64) && ENABLE_SSE + { + __m128i fnv_prime = _mm_set1_epi32(FNV_PRIME); + __m128i xmm0 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[0]); + __m128i xmm1 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[1]); + __m128i xmm2 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[2]); + __m128i xmm3 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[3]); + mix[n].xmm[0] = _mm_xor_si128(xmm0, dag_node->xmm[0]); + mix[n].xmm[1] = _mm_xor_si128(xmm1, dag_node->xmm[1]); + mix[n].xmm[2] = _mm_xor_si128(xmm2, dag_node->xmm[2]); + mix[n].xmm[3] = _mm_xor_si128(xmm3, dag_node->xmm[3]); + } + #else + { + for (unsigned w = 0; w != NODE_WORDS; ++w) { + mix[n].words[w] = fnv_hash(mix[n].words[w], dag_node->words[w]); + } + } #endif + } + + } + + // compress mix + for (uint32_t w = 0; w != MIX_WORDS; w += 4) { + uint32_t reduction = mix->words[w + 0]; + reduction = reduction * FNV_PRIME ^ mix->words[w + 1]; + reduction = reduction * FNV_PRIME ^ mix->words[w + 2]; + reduction = reduction * FNV_PRIME ^ mix->words[w + 3]; + mix->words[w / 4] = reduction; + } + + fix_endian_arr32(mix->words, MIX_WORDS / 4); + memcpy(&ret->mix_hash, mix->bytes, 32); + // final Keccak hash + SHA3_256(&ret->result, s_mix->bytes, 64 + 32); // Keccak-256(s + compressed_mix) + return true; +} - // compute sha3-512 hash and replicate across mix - SHA3_512(s_mix->bytes, s_mix->bytes, 40); - -#if BYTE_ORDER != LITTLE_ENDIAN - for (unsigned w = 0; w != 16; ++w) { - s_mix[0].words[w] = fix_endian32(s_mix[0].words[w]); - } -#endif +void ethash_quick_hash( + ethash_h256_t* return_hash, + ethash_h256_t const* header_hash, + uint64_t const nonce, + ethash_h256_t const* mix_hash +) +{ + uint8_t buf[64 + 32]; + memcpy(buf, header_hash, 32); + fix_endian64_same(nonce); + memcpy(&(buf[32]), &nonce, 8); + SHA3_512(buf, buf, 40); + memcpy(&(buf[64]), mix_hash, 32); + SHA3_256(return_hash, buf, 64 + 32); +} - node *const mix = s_mix + 1; - for (unsigned w = 0; w != MIX_WORDS; ++w) { - mix->words[w] = s_mix[0].words[w % NODE_WORDS]; - } +ethash_h256_t ethash_get_seedhash(uint64_t block_number) +{ + ethash_h256_t ret; + ethash_h256_reset(&ret); + uint64_t const epochs = block_number / ETHASH_EPOCH_LENGTH; + for (uint32_t i = 0; i < epochs; ++i) + SHA3_256(&ret, (uint8_t*)&ret, 32); + return ret; +} - unsigned const - page_size = sizeof(uint32_t) * MIX_WORDS, - num_full_pages = (unsigned) (params->full_size / page_size); +bool ethash_quick_check_difficulty( + ethash_h256_t const* header_hash, + uint64_t const nonce, + ethash_h256_t const* mix_hash, + ethash_h256_t const* difficulty +) +{ + + ethash_h256_t return_hash; + ethash_quick_hash(&return_hash, header_hash, nonce, mix_hash); + return ethash_check_difficulty(&return_hash, difficulty); +} +ethash_light_t ethash_light_new_internal(uint64_t cache_size, ethash_h256_t const* seed) +{ + struct ethash_light *ret; + ret = calloc(sizeof(*ret), 1); + if (!ret) { + return NULL; + } + ret->cache = malloc((size_t)cache_size); + if (!ret->cache) { + goto fail_free_light; + } + node* nodes = (node*)ret->cache; + if (!ethash_compute_cache_nodes(nodes, cache_size, seed)) { + goto fail_free_cache_mem; + } + ret->cache_size = cache_size; + return ret; + +fail_free_cache_mem: + free(ret->cache); +fail_free_light: + free(ret); + return NULL; +} - for (unsigned i = 0; i != ETHASH_ACCESSES; ++i) { - uint32_t const index = ((s_mix->words[0] ^ i) * FNV_PRIME ^ mix->words[i % MIX_WORDS]) % num_full_pages; +ethash_light_t ethash_light_new(uint64_t block_number) +{ + ethash_h256_t seedhash = ethash_get_seedhash(block_number); + ethash_light_t ret; + ret = ethash_light_new_internal(ethash_get_cachesize(block_number), &seedhash); + ret->block_number = block_number; + return ret; +} - for (unsigned n = 0; n != MIX_NODES; ++n) { - const node *dag_node = &full_nodes[MIX_NODES * index + n]; +void ethash_light_delete(ethash_light_t light) +{ + if (light->cache) { + free(light->cache); + } + free(light); +} - if (!full_nodes) { - node tmp_node; - ethash_calculate_dag_item(&tmp_node, index * MIX_NODES + n, params, cache); - dag_node = &tmp_node; - } +ethash_return_value_t ethash_light_compute_internal( + ethash_light_t light, + uint64_t full_size, + ethash_h256_t const header_hash, + uint64_t nonce +) +{ + ethash_return_value_t ret; + ret.success = true; + if (!ethash_hash(&ret, NULL, light, full_size, header_hash, nonce)) { + ret.success = false; + } + return ret; +} -#if defined(_M_X64) && ENABLE_SSE - { - __m128i fnv_prime = _mm_set1_epi32(FNV_PRIME); - __m128i xmm0 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[0]); - __m128i xmm1 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[1]); - __m128i xmm2 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[2]); - __m128i xmm3 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[3]); - mix[n].xmm[0] = _mm_xor_si128(xmm0, dag_node->xmm[0]); - mix[n].xmm[1] = _mm_xor_si128(xmm1, dag_node->xmm[1]); - mix[n].xmm[2] = _mm_xor_si128(xmm2, dag_node->xmm[2]); - mix[n].xmm[3] = _mm_xor_si128(xmm3, dag_node->xmm[3]); - } - #else - { - for (unsigned w = 0; w != NODE_WORDS; ++w) { - mix[n].words[w] = fnv_hash(mix[n].words[w], dag_node->words[w]); - } - } -#endif - } - - } - - // compress mix - for (unsigned w = 0; w != MIX_WORDS; w += 4) { - uint32_t reduction = mix->words[w + 0]; - reduction = reduction * FNV_PRIME ^ mix->words[w + 1]; - reduction = reduction * FNV_PRIME ^ mix->words[w + 2]; - reduction = reduction * FNV_PRIME ^ mix->words[w + 3]; - mix->words[w / 4] = reduction; - } - -#if BYTE_ORDER != LITTLE_ENDIAN - for (unsigned w = 0; w != MIX_WORDS/4; ++w) { - mix->words[w] = fix_endian32(mix->words[w]); - } -#endif +ethash_return_value_t ethash_light_compute( + ethash_light_t light, + ethash_h256_t const header_hash, + uint64_t nonce +) +{ + uint64_t full_size = ethash_get_datasize(light->block_number); + return ethash_light_compute_internal(light, full_size, header_hash, nonce); +} - memcpy(ret->mix_hash, mix->bytes, 32); - // final Keccak hash - SHA3_256(ret->result, s_mix->bytes, 64 + 32); // Keccak-256(s + compressed_mix) +static bool ethash_mmap(struct ethash_full* ret, FILE* f) +{ + int fd; + char* mmapped_data; + ret->file = f; + if ((fd = ethash_fileno(ret->file)) == -1) { + return false; + } + mmapped_data= mmap( + NULL, + (size_t)ret->file_size + ETHASH_DAG_MAGIC_NUM_SIZE, + PROT_READ | PROT_WRITE, + MAP_SHARED, + fd, + 0 + ); + if (mmapped_data == MAP_FAILED) { + return false; + } + ret->data = (node*)(mmapped_data + ETHASH_DAG_MAGIC_NUM_SIZE); + return true; } -void ethash_quick_hash( - uint8_t return_hash[32], - const uint8_t header_hash[32], - const uint64_t nonce, - const uint8_t mix_hash[32]) { - - uint8_t buf[64 + 32]; - memcpy(buf, header_hash, 32); -#if BYTE_ORDER != LITTLE_ENDIAN - nonce = fix_endian64(nonce); -#endif - memcpy(&(buf[32]), &nonce, 8); - SHA3_512(buf, buf, 40); - memcpy(&(buf[64]), mix_hash, 32); - SHA3_256(return_hash, buf, 64 + 32); +ethash_full_t ethash_full_new_internal( + char const* dirname, + ethash_h256_t const seed_hash, + uint64_t full_size, + ethash_light_t const light, + ethash_callback_t callback +) +{ + struct ethash_full* ret; + FILE *f = NULL; + ret = calloc(sizeof(*ret), 1); + if (!ret) { + return NULL; + } + ret->file_size = (size_t)full_size; + switch (ethash_io_prepare(dirname, seed_hash, &f, (size_t)full_size, false)) { + case ETHASH_IO_FAIL: + goto fail_free_full; + case ETHASH_IO_MEMO_MATCH: + if (!ethash_mmap(ret, f)) { + goto fail_close_file; + } + return ret; + case ETHASH_IO_MEMO_SIZE_MISMATCH: + // if a DAG of same filename but unexpected size is found, silently force new file creation + if (ethash_io_prepare(dirname, seed_hash, &f, (size_t)full_size, true) != ETHASH_IO_MEMO_MISMATCH) { + goto fail_free_full; + } + // fallthrough to the mismatch case here, DO NOT go through match + case ETHASH_IO_MEMO_MISMATCH: + if (!ethash_mmap(ret, f)) { + goto fail_close_file; + } + break; + } + + if (!ethash_compute_full_data(ret->data, full_size, light, callback)) { + goto fail_free_full_data; + } + + // after the DAG has been filled then we finalize it by writting the magic number at the beginning + if (fseek(f, 0, SEEK_SET) != 0) { + goto fail_free_full_data; + } + uint64_t const magic_num = ETHASH_DAG_MAGIC_NUM; + if (fwrite(&magic_num, ETHASH_DAG_MAGIC_NUM_SIZE, 1, f) != 1) { + goto fail_free_full_data; + } + fflush(f); // make sure the magic number IS there + return ret; + +fail_free_full_data: + // could check that munmap(..) == 0 but even if it did not can't really do anything here + munmap(ret->data, (size_t)full_size); +fail_close_file: + fclose(ret->file); +fail_free_full: + free(ret); + return NULL; } -void ethash_get_seedhash(uint8_t seedhash[32], const uint32_t block_number) { - memset(seedhash, 0, 32); - const uint32_t epochs = block_number / ETHASH_EPOCH_LENGTH; - for (uint32_t i = 0; i < epochs; ++i) - SHA3_256(seedhash, seedhash, 32); +ethash_full_t ethash_full_new(ethash_light_t light, ethash_callback_t callback) +{ + char strbuf[256]; + if (!ethash_get_default_dirname(strbuf, 256)) { + return NULL; + } + uint64_t full_size = ethash_get_datasize(light->block_number); + ethash_h256_t seedhash = ethash_get_seedhash(light->block_number); + return ethash_full_new_internal(strbuf, seedhash, full_size, light, callback); } -int ethash_preliminary_check_boundary( - const uint8_t header_hash[32], - const uint64_t nonce, - const uint8_t mix_hash[32], - const uint8_t difficulty[32]) { +void ethash_full_delete(ethash_full_t full) +{ + // could check that munmap(..) == 0 but even if it did not can't really do anything here + munmap(full->data, (size_t)full->file_size); + if (full->file) { + fclose(full->file); + } + free(full); +} - uint8_t return_hash[32]; - ethash_quick_hash(return_hash, header_hash, nonce, mix_hash); - return ethash_leq_be256(return_hash, difficulty); +ethash_return_value_t ethash_full_compute( + ethash_full_t full, + ethash_h256_t const header_hash, + uint64_t nonce +) +{ + ethash_return_value_t ret; + ret.success = true; + if (!ethash_hash( + &ret, + (node const*)full->data, + NULL, + full->file_size, + header_hash, + nonce)) { + ret.success = false; + } + return ret; } -void ethash_full(ethash_return_value *ret, void const *full_mem, ethash_params const *params, const uint8_t previous_hash[32], const uint64_t nonce) { - ethash_hash(ret, (node const *) full_mem, NULL, params, previous_hash, nonce); +void const* ethash_full_dag(ethash_full_t full) +{ + return full->data; } -void ethash_light(ethash_return_value *ret, void const *cache, ethash_params const *params, const uint8_t previous_hash[32], const uint64_t nonce) { - ethash_hash(ret, NULL, cache, params, previous_hash, nonce); +uint64_t ethash_full_dag_size(ethash_full_t full) +{ + return full->file_size; } diff --git a/libethash/internal.h b/libethash/internal.h index dec7e6b13..4e2b695ac 100644 --- a/libethash/internal.h +++ b/libethash/internal.h @@ -2,6 +2,7 @@ #include "compiler.h" #include "endian.h" #include "ethash.h" +#include #define ENABLE_SSE 0 @@ -20,9 +21,9 @@ extern "C" { #include typedef union node { - uint8_t bytes[NODE_WORDS * 4]; - uint32_t words[NODE_WORDS]; - uint64_t double_words[NODE_WORDS / 2]; + uint8_t bytes[NODE_WORDS * 4]; + uint32_t words[NODE_WORDS]; + uint64_t double_words[NODE_WORDS / 2]; #if defined(_M_X64) && ENABLE_SSE __m128i xmm[NODE_WORDS/4]; @@ -30,18 +31,139 @@ typedef union node { } node; +static inline uint8_t ethash_h256_get(ethash_h256_t const* hash, unsigned int i) +{ + return hash->b[i]; +} + +static inline void ethash_h256_set(ethash_h256_t* hash, unsigned int i, uint8_t v) +{ + hash->b[i] = v; +} + +static inline void ethash_h256_reset(ethash_h256_t* hash) +{ + memset(hash, 0, 32); +} + +// Returns if hash is less than or equal to difficulty +static inline bool ethash_check_difficulty( + ethash_h256_t const* hash, + ethash_h256_t const* difficulty +) +{ + // Difficulty is big endian + for (int i = 0; i < 32; i++) { + if (ethash_h256_get(hash, i) == ethash_h256_get(difficulty, i)) { + continue; + } + return ethash_h256_get(hash, i) < ethash_h256_get(difficulty, i); + } + return true; +} + +bool ethash_quick_check_difficulty( + ethash_h256_t const* header_hash, + uint64_t const nonce, + ethash_h256_t const* mix_hash, + ethash_h256_t const* difficulty +); + +struct ethash_light { + void* cache; + uint64_t cache_size; + uint64_t block_number; +}; + +/** + * Allocate and initialize a new ethash_light handler. Internal version + * + * @param cache_size The size of the cache in bytes + * @param seed Block seedhash to be used during the computation of the + * cache nodes + * @return Newly allocated ethash_light handler or NULL in case of + * ERRNOMEM or invalid parameters used for @ref ethash_compute_cache_nodes() + */ +ethash_light_t ethash_light_new_internal(uint64_t cache_size, ethash_h256_t const* seed); + +/** + * Calculate the light client data. Internal version. + * + * @param light The light client handler + * @param full_size The size of the full data in bytes. + * @param header_hash The header hash to pack into the mix + * @param nonce The nonce to pack into the mix + * @return The resulting hash. + */ +ethash_return_value_t ethash_light_compute_internal( + ethash_light_t light, + uint64_t full_size, + ethash_h256_t const header_hash, + uint64_t nonce +); + +struct ethash_full { + FILE* file; + uint64_t file_size; + node* data; +}; + +/** + * Allocate and initialize a new ethash_full handler. Internal version. + * + * @param dirname The directory in which to put the DAG file. + * @param seedhash The seed hash of the block. Used in the DAG file naming. + * @param full_size The size of the full data in bytes. + * @param cache A cache object to use that was allocated with @ref ethash_cache_new(). + * Iff this function succeeds the ethash_full_t will take memory + * memory ownership of the cache and free it at deletion. If + * not then the user still has to handle freeing of the cache himself. + * @param callback A callback function with signature of @ref ethash_callback_t + * It accepts an unsigned with which a progress of DAG calculation + * can be displayed. If all goes well the callback should return 0. + * If a non-zero value is returned then DAG generation will stop. + * @return Newly allocated ethash_full handler or NULL in case of + * ERRNOMEM or invalid parameters used for @ref ethash_compute_full_data() + */ +ethash_full_t ethash_full_new_internal( + char const* dirname, + ethash_h256_t const seed_hash, + uint64_t full_size, + ethash_light_t const light, + ethash_callback_t callback +); + void ethash_calculate_dag_item( - node *const ret, - const unsigned node_index, - ethash_params const *params, - void const *cache + node* const ret, + uint32_t node_index, + ethash_light_t const cache ); void ethash_quick_hash( - uint8_t return_hash[32], - const uint8_t header_hash[32], - const uint64_t nonce, - const uint8_t mix_hash[32]); + ethash_h256_t* return_hash, + ethash_h256_t const* header_hash, + const uint64_t nonce, + ethash_h256_t const* mix_hash +); + +uint64_t ethash_get_datasize(uint64_t const block_number); +uint64_t ethash_get_cachesize(uint64_t const block_number); + +/** + * Compute the memory data for a full node's memory + * + * @param mem A pointer to an ethash full's memory + * @param full_size The size of the full data in bytes + * @param cache A cache object to use in the calculation + * @param callback The callback function. Check @ref ethash_full_new() for details. + * @return true if all went fine and false for invalid parameters + */ +bool ethash_compute_full_data( + void* mem, + uint64_t full_size, + ethash_light_t const light, + ethash_callback_t callback +); #ifdef __cplusplus } diff --git a/libethash/io.c b/libethash/io.c index 07387caaf..5b4e7da2b 100644 --- a/libethash/io.c +++ b/libethash/io.c @@ -22,68 +22,81 @@ #include #include -// silly macro to save some typing -#define PASS_ARR(c_) (c_), sizeof(c_) - -static bool ethash_io_write_file(char const *dirname, - char const* filename, - size_t filename_length, - void const* data, - size_t data_size) -{ - bool ret = false; - char *fullname = ethash_io_create_filename(dirname, filename, filename_length); - if (!fullname) { - return false; - } - FILE *f = fopen(fullname, "wb"); - if (!f) { - goto free_name; - } - if (data_size != fwrite(data, 1, data_size, f)) { - goto close; - } - - ret = true; -close: - fclose(f); -free_name: - free(fullname); - return ret; -} - -bool ethash_io_write(char const *dirname, - ethash_params const* params, - ethash_blockhash_t seedhash, - void const* cache, - uint8_t **data, - size_t *data_size) +enum ethash_io_rc ethash_io_prepare( + char const* dirname, + ethash_h256_t const seedhash, + FILE** output_file, + uint64_t file_size, + bool force_create +) { - char info_buffer[DAG_MEMO_BYTESIZE]; - // allocate the bytes - uint8_t *temp_data_ptr = malloc((size_t)params->full_size); - if (!temp_data_ptr) { - goto end; - } - ethash_compute_full_data(temp_data_ptr, params, cache); + char mutable_name[DAG_MUTABLE_NAME_MAX_SIZE]; + enum ethash_io_rc ret = ETHASH_IO_FAIL; - if (!ethash_io_write_file(dirname, PASS_ARR(DAG_FILE_NAME), temp_data_ptr, (size_t)params->full_size)) { - goto fail_free; - } + // assert directory exists + if (!ethash_mkdir(dirname)) { + goto end; + } - ethash_io_serialize_info(ETHASH_REVISION, seedhash, info_buffer); - if (!ethash_io_write_file(dirname, PASS_ARR(DAG_MEMO_NAME), info_buffer, DAG_MEMO_BYTESIZE)) { - goto fail_free; - } + ethash_io_mutable_name(ETHASH_REVISION, &seedhash, mutable_name); + char* tmpfile = ethash_io_create_filename(dirname, mutable_name, strlen(mutable_name)); + if (!tmpfile) { + goto end; + } - *data = temp_data_ptr; - *data_size = (size_t)params->full_size; - return true; + FILE *f; + if (!force_create) { + // try to open the file + f = ethash_fopen(tmpfile, "rb+"); + if (f) { + size_t found_size; + if (!ethash_file_size(f, &found_size)) { + fclose(f); + goto free_memo; + } + if (file_size != found_size - ETHASH_DAG_MAGIC_NUM_SIZE) { + fclose(f); + ret = ETHASH_IO_MEMO_SIZE_MISMATCH; + goto free_memo; + } + // compare the magic number, no need to care about endianess since it's local + uint64_t magic_num; + if (fread(&magic_num, ETHASH_DAG_MAGIC_NUM_SIZE, 1, f) != 1) { + // I/O error + fclose(f); + ret = ETHASH_IO_MEMO_SIZE_MISMATCH; + goto free_memo; + } + if (magic_num != ETHASH_DAG_MAGIC_NUM) { + fclose(f); + ret = ETHASH_IO_MEMO_SIZE_MISMATCH; + goto free_memo; + } + ret = ETHASH_IO_MEMO_MATCH; + goto set_file; + } + } + + // file does not exist, will need to be created + f = ethash_fopen(tmpfile, "wb+"); + if (!f) { + goto free_memo; + } + // make sure it's of the proper size + if (fseek(f, (long int)(file_size + ETHASH_DAG_MAGIC_NUM_SIZE - 1), SEEK_SET) != 0) { + fclose(f); + goto free_memo; + } + fputc('\n', f); + fflush(f); + ret = ETHASH_IO_MEMO_MISMATCH; + goto set_file; -fail_free: - free(temp_data_ptr); + ret = ETHASH_IO_MEMO_MATCH; +set_file: + *output_file = f; +free_memo: + free(tmpfile); end: - return false; + return ret; } - -#undef PASS_ARR diff --git a/libethash/io.h b/libethash/io.h index 0fa292362..05aa5ed37 100644 --- a/libethash/io.h +++ b/libethash/io.h @@ -22,94 +22,163 @@ #include #include #include +#include +#ifdef __cplusplus +#define __STDC_FORMAT_MACROS 1 +#endif +#include +#include "endian.h" #include "ethash.h" #ifdef __cplusplus extern "C" { #endif - -typedef struct ethash_blockhash { uint8_t b[32]; } ethash_blockhash_t; - -static const char DAG_FILE_NAME[] = "full"; -static const char DAG_MEMO_NAME[] = "full.info"; -// MSVC thinks that "static const unsigned int" is not a compile time variable. Sorry for the #define :( -#define DAG_MEMO_BYTESIZE 36 - +// Maximum size for mutable part of DAG file name +// 6 is for "full-R", the suffix of the filename +// 10 is for maximum number of digits of a uint32_t (for REVISION) +// 1 is for - and 16 is for the first 16 hex digits for first 8 bytes of +// the seedhash and last 1 is for the null terminating character +// Reference: https://github.com/ethereum/wiki/wiki/Ethash-DAG +#define DAG_MUTABLE_NAME_MAX_SIZE (6 + 10 + 1 + 16 + 1) /// Possible return values of @see ethash_io_prepare enum ethash_io_rc { - ETHASH_IO_FAIL = 0, ///< There has been an IO failure - ETHASH_IO_MEMO_MISMATCH, ///< Memo file either did not exist or there was content mismatch - ETHASH_IO_MEMO_MATCH, ///< Memo file existed and contents matched. No need to do anything + ETHASH_IO_FAIL = 0, ///< There has been an IO failure + ETHASH_IO_MEMO_SIZE_MISMATCH, ///< DAG with revision/hash match, but file size was wrong. + ETHASH_IO_MEMO_MISMATCH, ///< The DAG file did not exist or there was revision/hash mismatch + ETHASH_IO_MEMO_MATCH, ///< DAG file existed and revision/hash matched. No need to do anything }; +// small hack for windows. I don't feel I should use va_args and forward just +// to have this one function properly cross-platform abstracted +#if defined(_WIN32) && !defined(__GNUC__) +#define snprintf(...) sprintf_s(__VA_ARGS__) +#endif + /** * Prepares io for ethash * - * Create the DAG directory if it does not exist, and check if the memo file matches. - * If it does not match then it's deleted to pave the way for @ref ethash_io_write() + * Create the DAG directory and the DAG file if they don't exist. * - * @param dirname A null terminated c-string of the path of the ethash - * data directory. If it does not exist it's created. - * @param seedhash The seedhash of the current block number - * @return For possible return values @see enum ethash_io_rc + * @param[in] dirname A null terminated c-string of the path of the ethash + * data directory. If it does not exist it's created. + * @param[in] seedhash The seedhash of the current block number, used in the + * naming of the file as can be seen from the spec at: + * https://github.com/ethereum/wiki/wiki/Ethash-DAG + * @param[out] output_file If there was no failure then this will point to an open + * file descriptor. User is responsible for closing it. + * In the case of memo match then the file is open on read + * mode, while on the case of mismatch a new file is created + * on write mode + * @param[in] file_size The size that the DAG file should have on disk + * @param[out] force_create If true then there is no check to see if the file + * already exists + * @return For possible return values @see enum ethash_io_rc */ -enum ethash_io_rc ethash_io_prepare(char const *dirname, ethash_blockhash_t seedhash); +enum ethash_io_rc ethash_io_prepare( + char const* dirname, + ethash_h256_t const seedhash, + FILE** output_file, + uint64_t file_size, + bool force_create +); + /** - * Fully computes data and writes it to the file on disk. + * An fopen wrapper for no-warnings crossplatform fopen. * - * This function should be called after @see ethash_io_prepare() and only if - * its return value is @c ETHASH_IO_MEMO_MISMATCH. Will write both the full data - * and the memo file. + * Msvc compiler considers fopen to be insecure and suggests to use their + * alternative. This is a wrapper for this alternative. Another way is to + * #define _CRT_SECURE_NO_WARNINGS, but disabling all security warnings does + * not sound like a good idea. * - * @param[in] dirname A null terminated c-string of the path of the ethash - * data directory. Has to exist. - * @param[in] params An ethash_params object containing the full size - * and the cache size - * @param[in] seedhash The seedhash of the current block number - * @param[in] cache The cache data. Would have usually been calulated by - * @see ethash_prep_light(). - * @param[out] data Pass a pointer to uint8_t by reference here. If the - * function is succesfull then this point to the allocated - * data calculated by @see ethash_prep_full(). Memory - * ownership is transfered to the callee. Remember that - * you eventually need to free this with a call to free(). - * @param[out] data_size Pass a size_t by value. If the function is succesfull - * then this will contain the number of bytes allocated - * for @a data. - * @return True for success and false in case of failure. + * @param file_name The path to the file to open + * @param mode Opening mode. Check fopen() + * @return The FILE* or NULL in failure */ -bool ethash_io_write(char const *dirname, - ethash_params const* params, - ethash_blockhash_t seedhash, - void const* cache, - uint8_t **data, - size_t *data_size); +FILE* ethash_fopen(char const* file_name, char const* mode); -static inline void ethash_io_serialize_info(uint32_t revision, - ethash_blockhash_t seed_hash, - char *output) -{ - // if .info is only consumed locally we don't really care about endianess - memcpy(output, &revision, 4); - memcpy(output + 4, &seed_hash, 32); -} +/** + * An strncat wrapper for no-warnings crossplatform strncat. + * + * Msvc compiler considers strncat to be insecure and suggests to use their + * alternative. This is a wrapper for this alternative. Another way is to + * #define _CRT_SECURE_NO_WARNINGS, but disabling all security warnings does + * not sound like a good idea. + * + * @param des Destination buffer + * @param dest_size Maximum size of the destination buffer. This is the + * extra argument for the MSVC secure strncat + * @param src Souce buffer + * @param count Number of bytes to copy from source + * @return If all is well returns the dest buffer. If there is an + * error returns NULL + */ +char* ethash_strncat(char* dest, size_t dest_size, char const* src, size_t count); -static inline char *ethash_io_create_filename(char const *dirname, - char const* filename, - size_t filename_length) -{ - // in C the cast is not needed, but a C++ compiler will complain for invalid conversion - char *name = (char*)malloc(strlen(dirname) + filename_length); - if (!name) { - return NULL; - } +/** + * A cross-platform mkdir wrapper to create a directory or assert it's there + * + * @param dirname The full path of the directory to create + * @return true if the directory was created or if it already + * existed + */ +bool ethash_mkdir(char const* dirname); - name[0] = '\0'; - strcat(name, dirname); - strcat(name, filename); - return name; -} +/** + * Get a file's size + * + * @param[in] f The open file stream whose size to get + * @param[out] size Pass a size_t by reference to contain the file size + * @return true in success and false if there was a failure + */ +bool ethash_file_size(FILE* f, size_t* ret_size); + +/** + * Get a file descriptor number from a FILE stream + * + * @param f The file stream whose fd to get + * @return Platform specific fd handler + */ +int ethash_fileno(FILE* f); + +/** + * Create the filename for the DAG. + * + * @param dirname The directory name in which the DAG file should reside + * If it does not end with a directory separator it is appended. + * @param filename The actual name of the file + * @param filename_length The length of the filename in bytes + * @return A char* containing the full name. User must deallocate. + */ +char* ethash_io_create_filename( + char const* dirname, + char const* filename, + size_t filename_length +); + +/** + * Gets the default directory name for the DAG depending on the system + * + * The spec defining this directory is here: https://github.com/ethereum/wiki/wiki/Ethash-DAG + * + * @param[out] strbuf A string buffer of sufficient size to keep the + * null termninated string of the directory name + * @param[in] buffsize Size of @a strbuf in bytes + * @return true for success and false otherwise + */ +bool ethash_get_default_dirname(char* strbuf, size_t buffsize); +static inline bool ethash_io_mutable_name( + uint32_t revision, + ethash_h256_t const* seed_hash, + char* output +) +{ + uint64_t hash = *((uint64_t*)seed_hash); +#if LITTLE_ENDIAN == BYTE_ORDER + hash = ethash_swap_u64(hash); +#endif + return snprintf(output, DAG_MUTABLE_NAME_MAX_SIZE, "full-R%u-%016" PRIx64, revision, hash) >= 0; +} #ifdef __cplusplus } diff --git a/libethash/io_posix.c b/libethash/io_posix.c index 9d9ccac69..7f03d5482 100644 --- a/libethash/io_posix.c +++ b/libethash/io_posix.c @@ -27,50 +27,76 @@ #include #include -enum ethash_io_rc ethash_io_prepare(char const *dirname, ethash_blockhash_t seedhash) +FILE* ethash_fopen(char const* file_name, char const* mode) { - char read_buffer[DAG_MEMO_BYTESIZE]; - char expect_buffer[DAG_MEMO_BYTESIZE]; - enum ethash_io_rc ret = ETHASH_IO_FAIL; + return fopen(file_name, mode); +} - // assert directory exists, full owner permissions and read/search for others - int rc = mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - if (rc == -1 && errno != EEXIST) { - goto end; - } +char* ethash_strncat(char* dest, size_t dest_size, char const* src, size_t count) +{ + return strlen(dest) + count + 1 <= dest_size ? strncat(dest, src, count) : NULL; +} - char *memofile = ethash_io_create_filename(dirname, DAG_MEMO_NAME, sizeof(DAG_MEMO_NAME)); - if (!memofile) { - goto end; - } +bool ethash_mkdir(char const* dirname) +{ + int rc = mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + return rc != -1 || errno == EEXIST; +} - // try to open memo file - FILE *f = fopen(memofile, "rb"); - if (!f) { - // file does not exist, so no checking happens. All is fine. - ret = ETHASH_IO_MEMO_MISMATCH; - goto free_memo; - } +int ethash_fileno(FILE *f) +{ + return fileno(f); +} - if (fread(read_buffer, 1, DAG_MEMO_BYTESIZE, f) != DAG_MEMO_BYTESIZE) { - goto close; - } +char* ethash_io_create_filename( + char const* dirname, + char const* filename, + size_t filename_length +) +{ + size_t dirlen = strlen(dirname); + size_t dest_size = dirlen + filename_length + 1; + if (dirname[dirlen] != '/') { + dest_size += 1; + } + char* name = malloc(dest_size); + if (!name) { + return NULL; + } - ethash_io_serialize_info(ETHASH_REVISION, seedhash, expect_buffer); - if (memcmp(read_buffer, expect_buffer, DAG_MEMO_BYTESIZE) != 0) { - // we have different memo contents so delete the memo file - if (unlink(memofile) != 0) { - goto close; - } - ret = ETHASH_IO_MEMO_MISMATCH; - } + name[0] = '\0'; + ethash_strncat(name, dest_size, dirname, dirlen); + if (dirname[dirlen] != '/') { + ethash_strncat(name, dest_size, "/", 1); + } + ethash_strncat(name, dest_size, filename, filename_length); + return name; +} - ret = ETHASH_IO_MEMO_MATCH; +bool ethash_file_size(FILE* f, size_t* ret_size) +{ + struct stat st; + int fd; + if ((fd = fileno(f)) == -1 || fstat(fd, &st) != 0) { + return false; + } + *ret_size = st.st_size; + return true; +} -close: - fclose(f); -free_memo: - free(memofile); -end: - return ret; +bool ethash_get_default_dirname(char* strbuf, size_t buffsize) +{ + static const char dir_suffix[] = ".ethash/"; + strbuf[0] = '\0'; + char* home_dir = getenv("HOME"); + size_t len = strlen(home_dir); + if (!ethash_strncat(strbuf, buffsize, home_dir, len)) { + return false; + } + if (home_dir[len] != '/') { + if (!ethash_strncat(strbuf, buffsize, "/", 1)) { + return false; + } + } + return ethash_strncat(strbuf, buffsize, dir_suffix, sizeof(dir_suffix)); } diff --git a/libethash/io_win32.c b/libethash/io_win32.c index 77367fdd9..2e6c8deb8 100644 --- a/libethash/io_win32.c +++ b/libethash/io_win32.c @@ -23,51 +23,78 @@ #include #include #include +#include +#include +#include -enum ethash_io_rc ethash_io_prepare(char const *dirname, ethash_blockhash_t seedhash) +FILE* ethash_fopen(char const* file_name, char const* mode) { - char read_buffer[DAG_MEMO_BYTESIZE]; - char expect_buffer[DAG_MEMO_BYTESIZE]; - enum ethash_io_rc ret = ETHASH_IO_FAIL; + FILE* f; + return fopen_s(&f, file_name, mode) == 0 ? f : NULL; +} - // assert directory exists - int rc = _mkdir(dirname); - if (rc == -1 && errno != EEXIST) { - goto end; - } +char* ethash_strncat(char* dest, size_t dest_size, char const* src, size_t count) +{ + return strncat_s(dest, dest_size, src, count) == 0 ? dest : NULL; +} - char *memofile = ethash_io_create_filename(dirname, DAG_MEMO_NAME, sizeof(DAG_MEMO_NAME)); - if (!memofile) { - goto end; - } +bool ethash_mkdir(char const* dirname) +{ + int rc = _mkdir(dirname); + return rc != -1 || errno == EEXIST; +} - // try to open memo file - FILE *f = fopen(memofile, "rb"); - if (!f) { - // file does not exist, so no checking happens. All is fine. - ret = ETHASH_IO_MEMO_MISMATCH; - goto free_memo; - } +int ethash_fileno(FILE* f) +{ + return _fileno(f); +} - if (fread(read_buffer, 1, DAG_MEMO_BYTESIZE, f) != DAG_MEMO_BYTESIZE) { - goto close; - } +char* ethash_io_create_filename( + char const* dirname, + char const* filename, + size_t filename_length +) +{ + size_t dirlen = strlen(dirname); + size_t dest_size = dirlen + filename_length + 1; + if (dirname[dirlen] != '\\' || dirname[dirlen] != '/') { + dest_size += 1; + } + char* name = malloc(dest_size); + if (!name) { + return NULL; + } + + name[0] = '\0'; + ethash_strncat(name, dest_size, dirname, dirlen); + if (dirname[dirlen] != '\\' || dirname[dirlen] != '/') { + ethash_strncat(name, dest_size, "\\", 1); + } + ethash_strncat(name, dest_size, filename, filename_length); + return name; +} - ethash_io_serialize_info(ETHASH_REVISION, seedhash, expect_buffer); - if (memcmp(read_buffer, expect_buffer, DAG_MEMO_BYTESIZE) != 0) { - // we have different memo contents so delete the memo file - if (_unlink(memofile) != 0) { - goto close; - } - ret = ETHASH_IO_MEMO_MISMATCH; - } +bool ethash_file_size(FILE* f, size_t* ret_size) +{ + struct _stat st; + int fd; + if ((fd = _fileno(f)) == -1 || _fstat(fd, &st) != 0) { + return false; + } + *ret_size = st.st_size; + return true; +} - ret = ETHASH_IO_MEMO_MATCH; +bool ethash_get_default_dirname(char* strbuf, size_t buffsize) +{ + static const char dir_suffix[] = "Appdata\\Ethash\\"; + strbuf[0] = '\0'; + if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, (WCHAR*)strbuf))) { + return false; + } + if (!ethash_strncat(strbuf, buffsize, "\\", 1)) { + return false; + } -close: - fclose(f); -free_memo: - free(memofile); -end: - return ret; + return ethash_strncat(strbuf, buffsize, dir_suffix, sizeof(dir_suffix)); } diff --git a/libethash/mmap.h b/libethash/mmap.h new file mode 100644 index 000000000..1e226e83f --- /dev/null +++ b/libethash/mmap.h @@ -0,0 +1,47 @@ +/* + This file is part of ethash. + + ethash 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. + + ethash 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 ethash. If not, see . +*/ +/** @file mmap.h + * @author Lefteris Karapetsas + * @date 2015 + */ +#pragma once +#if defined(__MINGW32__) || defined(_WIN32) +#include + +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +/* This flag is only available in WinXP+ */ +#ifdef FILE_MAP_EXECUTE +#define PROT_EXEC 0x4 +#else +#define PROT_EXEC 0x0 +#define FILE_MAP_EXECUTE 0 +#endif + +#define MAP_SHARED 0x01 +#define MAP_PRIVATE 0x02 +#define MAP_ANONYMOUS 0x20 +#define MAP_ANON MAP_ANONYMOUS +#define MAP_FAILED ((void *) -1) + +void* mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset); +void munmap(void* addr, size_t length); +#else // posix, yay! ^_^ +#include +#endif + + diff --git a/libethash/mmap_win32.c b/libethash/mmap_win32.c new file mode 100644 index 000000000..42968b98a --- /dev/null +++ b/libethash/mmap_win32.c @@ -0,0 +1,84 @@ +/* mmap() replacement for Windows + * + * Author: Mike Frysinger + * Placed into the public domain + */ + +/* References: + * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx + * CloseHandle: http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx + * MapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx + * UnmapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx + */ + +#include +#include +#include "mmap.h" + +#ifdef __USE_FILE_OFFSET64 +# define DWORD_HI(x) (x >> 32) +# define DWORD_LO(x) ((x) & 0xffffffff) +#else +# define DWORD_HI(x) (0) +# define DWORD_LO(x) (x) +#endif + +void* mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset) +{ + if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) + return MAP_FAILED; + if (fd == -1) { + if (!(flags & MAP_ANON) || offset) + return MAP_FAILED; + } else if (flags & MAP_ANON) + return MAP_FAILED; + + DWORD flProtect; + if (prot & PROT_WRITE) { + if (prot & PROT_EXEC) + flProtect = PAGE_EXECUTE_READWRITE; + else + flProtect = PAGE_READWRITE; + } else if (prot & PROT_EXEC) { + if (prot & PROT_READ) + flProtect = PAGE_EXECUTE_READ; + else if (prot & PROT_EXEC) + flProtect = PAGE_EXECUTE; + } else + flProtect = PAGE_READONLY; + + off_t end = length + offset; + HANDLE mmap_fd, h; + if (fd == -1) + mmap_fd = INVALID_HANDLE_VALUE; + else + mmap_fd = (HANDLE)_get_osfhandle(fd); + h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL); + if (h == NULL) + return MAP_FAILED; + + DWORD dwDesiredAccess; + if (prot & PROT_WRITE) + dwDesiredAccess = FILE_MAP_WRITE; + else + dwDesiredAccess = FILE_MAP_READ; + if (prot & PROT_EXEC) + dwDesiredAccess |= FILE_MAP_EXECUTE; + if (flags & MAP_PRIVATE) + dwDesiredAccess |= FILE_MAP_COPY; + void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length); + if (ret == NULL) { + ret = MAP_FAILED; + } + // since we are handling the file ourselves with fd, close the Windows Handle here + CloseHandle(h); + return ret; +} + +void munmap(void* addr, size_t length) +{ + UnmapViewOfFile(addr); +} + +#undef DWORD_HI +#undef DWORD_LO diff --git a/libethash/sha3.c b/libethash/sha3.c index 0c28230b8..e72fe1018 100644 --- a/libethash/sha3.c +++ b/libethash/sha3.c @@ -17,65 +17,65 @@ /*** Constants. ***/ static const uint8_t rho[24] = \ - { 1, 3, 6, 10, 15, 21, - 28, 36, 45, 55, 2, 14, - 27, 41, 56, 8, 25, 43, - 62, 18, 39, 61, 20, 44}; + { 1, 3, 6, 10, 15, 21, + 28, 36, 45, 55, 2, 14, + 27, 41, 56, 8, 25, 43, + 62, 18, 39, 61, 20, 44}; static const uint8_t pi[24] = \ - {10, 7, 11, 17, 18, 3, - 5, 16, 8, 21, 24, 4, - 15, 23, 19, 13, 12, 2, - 20, 14, 22, 9, 6, 1}; + {10, 7, 11, 17, 18, 3, + 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, + 20, 14, 22, 9, 6, 1}; static const uint64_t RC[24] = \ - {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, - 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, - 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, - 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, - 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, - 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; + {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, + 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, + 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, + 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, + 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, + 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; /*** Helper macros to unroll the permutation. ***/ #define rol(x, s) (((x) << s) | ((x) >> (64 - s))) #define REPEAT6(e) e e e e e e #define REPEAT24(e) REPEAT6(e e e e) #define REPEAT5(e) e e e e e -#define FOR5(v, s, e) \ - v = 0; \ - REPEAT5(e; v += s;) +#define FOR5(v, s, e) \ + v = 0; \ + REPEAT5(e; v += s;) /*** Keccak-f[1600] ***/ static inline void keccakf(void* state) { - uint64_t* a = (uint64_t*)state; - uint64_t b[5] = {0}; - uint64_t t = 0; - uint8_t x, y; + uint64_t* a = (uint64_t*)state; + uint64_t b[5] = {0}; + uint64_t t = 0; + uint8_t x, y; - for (int i = 0; i < 24; i++) { - // Theta - FOR5(x, 1, - b[x] = 0; - FOR5(y, 5, - b[x] ^= a[x + y]; )) - FOR5(x, 1, - FOR5(y, 5, - a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); )) - // Rho and pi - t = a[1]; - x = 0; - REPEAT24(b[0] = a[pi[x]]; - a[pi[x]] = rol(t, rho[x]); - t = b[0]; - x++; ) - // Chi - FOR5(y, - 5, - FOR5(x, 1, - b[x] = a[y + x];) - FOR5(x, 1, - a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); )) - // Iota - a[0] ^= RC[i]; - } + for (int i = 0; i < 24; i++) { + // Theta + FOR5(x, 1, + b[x] = 0; + FOR5(y, 5, + b[x] ^= a[x + y]; )) + FOR5(x, 1, + FOR5(y, 5, + a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); )) + // Rho and pi + t = a[1]; + x = 0; + REPEAT24(b[0] = a[pi[x]]; + a[pi[x]] = rol(t, rho[x]); + t = b[0]; + x++; ) + // Chi + FOR5(y, + 5, + FOR5(x, 1, + b[x] = a[y + x];) + FOR5(x, 1, + a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); )) + // Iota + a[0] ^= RC[i]; + } } /******** The FIPS202-defined functions. ********/ @@ -83,20 +83,20 @@ static inline void keccakf(void* state) { /*** Some helper macros. ***/ #define _(S) do { S } while (0) -#define FOR(i, ST, L, S) \ - _(for (size_t i = 0; i < L; i += ST) { S; }) -#define mkapply_ds(NAME, S) \ - static inline void NAME(uint8_t* dst, \ - const uint8_t* src, \ - size_t len) { \ - FOR(i, 1, len, S); \ - } -#define mkapply_sd(NAME, S) \ - static inline void NAME(const uint8_t* src, \ - uint8_t* dst, \ - size_t len) { \ - FOR(i, 1, len, S); \ - } +#define FOR(i, ST, L, S) \ + _(for (size_t i = 0; i < L; i += ST) { S; }) +#define mkapply_ds(NAME, S) \ + static inline void NAME(uint8_t* dst, \ + const uint8_t* src, \ + size_t len) { \ + FOR(i, 1, len, S); \ + } +#define mkapply_sd(NAME, S) \ + static inline void NAME(const uint8_t* src, \ + uint8_t* dst, \ + size_t len) { \ + FOR(i, 1, len, S); \ + } mkapply_ds(xorin, dst[i] ^= src[i]) // xorin mkapply_sd(setout, dst[i] = src[i]) // setout @@ -105,47 +105,47 @@ mkapply_sd(setout, dst[i] = src[i]) // setout #define Plen 200 // Fold P*F over the full blocks of an input. -#define foldP(I, L, F) \ - while (L >= rate) { \ - F(a, I, rate); \ - P(a); \ - I += rate; \ - L -= rate; \ - } +#define foldP(I, L, F) \ + while (L >= rate) { \ + F(a, I, rate); \ + P(a); \ + I += rate; \ + L -= rate; \ + } /** The sponge-based hash construction. **/ static inline int hash(uint8_t* out, size_t outlen, - const uint8_t* in, size_t inlen, - size_t rate, uint8_t delim) { - if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) { - return -1; - } - uint8_t a[Plen] = {0}; - // Absorb input. - foldP(in, inlen, xorin); - // Xor in the DS and pad frame. - a[inlen] ^= delim; - a[rate - 1] ^= 0x80; - // Xor in the last block. - xorin(a, in, inlen); - // Apply P - P(a); - // Squeeze output. - foldP(out, outlen, setout); - setout(a, out, outlen); - memset(a, 0, 200); - return 0; + const uint8_t* in, size_t inlen, + size_t rate, uint8_t delim) { + if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) { + return -1; + } + uint8_t a[Plen] = {0}; + // Absorb input. + foldP(in, inlen, xorin); + // Xor in the DS and pad frame. + a[inlen] ^= delim; + a[rate - 1] ^= 0x80; + // Xor in the last block. + xorin(a, in, inlen); + // Apply P + P(a); + // Squeeze output. + foldP(out, outlen, setout); + setout(a, out, outlen); + memset(a, 0, 200); + return 0; } -#define defsha3(bits) \ - int sha3_##bits(uint8_t* out, size_t outlen, \ - const uint8_t* in, size_t inlen) { \ - if (outlen > (bits/8)) { \ - return -1; \ - } \ - return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \ - } +#define defsha3(bits) \ + int sha3_##bits(uint8_t* out, size_t outlen, \ + const uint8_t* in, size_t inlen) { \ + if (outlen > (bits/8)) { \ + return -1; \ + } \ + return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \ + } /*** FIPS202 SHA3 FOFs ***/ defsha3(256) -defsha3(512) \ No newline at end of file +defsha3(512) diff --git a/libethash/sha3.h b/libethash/sha3.h index 36a0a5301..a38006292 100644 --- a/libethash/sha3.h +++ b/libethash/sha3.h @@ -8,20 +8,24 @@ extern "C" { #include #include +struct ethash_h256; + #define decsha3(bits) \ - int sha3_##bits(uint8_t*, size_t, const uint8_t*, size_t); + int sha3_##bits(uint8_t*, size_t, uint8_t const*, size_t); decsha3(256) decsha3(512) -static inline void SHA3_256(uint8_t * const ret, uint8_t const *data, const size_t size) { - sha3_256(ret, 32, data, size); +static inline void SHA3_256(struct ethash_h256 const* ret, uint8_t const* data, size_t const size) +{ + sha3_256((uint8_t*)ret, 32, data, size); } -static inline void SHA3_512(uint8_t * const ret, uint8_t const *data, const size_t size) { - sha3_512(ret, 64, data, size); +static inline void SHA3_512(uint8_t* ret, uint8_t const* data, size_t const size) +{ + sha3_512(ret, 64, data, size); } #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/libethash/sha3_cryptopp.cpp b/libethash/sha3_cryptopp.cpp index 6cbbcad8f..2a7c02664 100644 --- a/libethash/sha3_cryptopp.cpp +++ b/libethash/sha3_cryptopp.cpp @@ -19,16 +19,19 @@ * @author Tim Hughes * @date 2015 */ - #include #include extern "C" { -void SHA3_256(uint8_t *const ret, const uint8_t *data, size_t size) { - CryptoPP::SHA3_256().CalculateDigest(ret, data, size); +struct ethash_h256; +typedef struct ethash_h256 ethash_h256_t; +void SHA3_256(ethash_h256_t const* ret, uint8_t const* data, size_t size) +{ + CryptoPP::SHA3_256().CalculateDigest((uint8_t*)ret, data, size); } -void SHA3_512(uint8_t *const ret, const uint8_t *data, size_t size) { - CryptoPP::SHA3_512().CalculateDigest(ret, data, size); +void SHA3_512(uint8_t* const ret, uint8_t const* data, size_t size) +{ + CryptoPP::SHA3_512().CalculateDigest(ret, data, size); +} } -} \ No newline at end of file diff --git a/libethash/sha3_cryptopp.h b/libethash/sha3_cryptopp.h index f910960e1..9edc407d5 100644 --- a/libethash/sha3_cryptopp.h +++ b/libethash/sha3_cryptopp.h @@ -2,14 +2,17 @@ #include "compiler.h" #include +#include #ifdef __cplusplus extern "C" { #endif -void SHA3_256(uint8_t *const ret, const uint8_t *data, size_t size); -void SHA3_512(uint8_t *const ret, const uint8_t *data, size_t size); +struct ethash_h256; + +void SHA3_256(struct ethash_h256 const* ret, uint8_t const* data, size_t size); +void SHA3_512(uint8_t* const ret, uint8_t const* data, size_t size); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/libethash/util.h b/libethash/util.h index 1e6d4fbab..c5fc6e55b 100644 --- a/libethash/util.h +++ b/libethash/util.h @@ -27,9 +27,9 @@ extern "C" { #endif #ifdef _MSC_VER -void debugf(const char *str, ...); +void debugf(char const* str, ...); #else -#define debugf(...) fprintf(stderr, __VA_ARGS__) +#define debugf printf #endif static inline uint32_t min_u32(uint32_t a, uint32_t b) diff --git a/libethash/util_win32.c b/libethash/util_win32.c new file mode 100644 index 000000000..268e6db05 --- /dev/null +++ b/libethash/util_win32.c @@ -0,0 +1,38 @@ +/* + 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 . +*/ +/** @file util.c + * @author Tim Hughes + * @date 2015 + */ +#include +#include +#include "util.h" + + +// foward declare without all of Windows.h +__declspec(dllimport) void __stdcall OutputDebugStringA(char const* lpOutputString); + +void debugf(char const* str, ...) +{ + va_list args; + va_start(args, str); + + char buf[1<<16]; + _vsnprintf_s(buf, sizeof(buf), sizeof(buf), str, args); + buf[sizeof(buf)-1] = '\0'; + OutputDebugStringA(buf); +} diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index 24fc1cb65..eb64593af 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -195,26 +195,18 @@ template h256 trieRootOver(unsigned _itemCount, T const& _get return t.root(); } +struct BlockInfoDiagnosticsChannel: public LogChannel { static const char* name() { return EthBlue "▧" EthWhite " ◌"; } static const int verbosity = 9; }; + void BlockInfo::verifyInternals(bytesConstRef _block) const { RLP root(_block); - /*OverlayDB db; - GenericTrieDB t(&db); - t.init(); - unsigned i = 0; - for (auto const& tr: root[1]) - { - bytes k = rlp(i); - t.insert(&k, tr.data()); - ++i; - } - if (transactionsRoot != t.root())*/ auto txList = root[1]; auto expectedRoot = trieRootOver(txList.itemCount(), [&](unsigned i){ return rlp(i); }, [&](unsigned i){ return txList[i].data(); }); + clog(BlockInfoDiagnosticsChannel) << "Expected trie root:" << toString(expectedRoot); if (transactionsRoot != expectedRoot) BOOST_THROW_EXCEPTION(InvalidTransactionsHash() << HashMismatchError(expectedRoot, transactionsRoot)); - + clog(BlockInfoDiagnosticsChannel) << "Expected uncle hash:" << toString(sha3(root[2].data())); if (sha3Uncles != sha3(root[2].data())) BOOST_THROW_EXCEPTION(InvalidUnclesHash()); } @@ -236,7 +228,7 @@ u256 BlockInfo::selectGasLimit(BlockInfo const& _parent) const return c_genesisGasLimit; else // target minimum of 3141592 - return max(max(c_minGasLimit, 3141592), (_parent.gasLimit * (c_gasLimitBoundDivisor - 1) + (_parent.gasUsed * 6 / 5)) / c_gasLimitBoundDivisor); + return max(max(c_minGasLimit, 3141592), _parent.gasLimit - _parent.gasLimit / c_gasLimitBoundDivisor + 1 + (_parent.gasUsed * 6 / 5) / c_gasLimitBoundDivisor); } u256 BlockInfo::calculateDifficulty(BlockInfo const& _parent) const @@ -254,9 +246,9 @@ void BlockInfo::verifyParent(BlockInfo const& _parent) const BOOST_THROW_EXCEPTION(InvalidDifficulty() << RequirementError((bigint)calculateDifficulty(_parent), (bigint)difficulty)); if (gasLimit < c_minGasLimit || - gasLimit < _parent.gasLimit * (c_gasLimitBoundDivisor - 1) / c_gasLimitBoundDivisor || - gasLimit > _parent.gasLimit * (c_gasLimitBoundDivisor + 1) / c_gasLimitBoundDivisor) - BOOST_THROW_EXCEPTION(InvalidGasLimit() << errinfo_min((bigint)_parent.gasLimit * (c_gasLimitBoundDivisor - 1) / c_gasLimitBoundDivisor) << errinfo_got((bigint)gasLimit) << errinfo_max((bigint)_parent.gasLimit * (c_gasLimitBoundDivisor + 1) / c_gasLimitBoundDivisor)); + gasLimit <= _parent.gasLimit - _parent.gasLimit / c_gasLimitBoundDivisor || + gasLimit >= _parent.gasLimit + _parent.gasLimit / c_gasLimitBoundDivisor) + BOOST_THROW_EXCEPTION(InvalidGasLimit() << errinfo_min((bigint)_parent.gasLimit - _parent.gasLimit / c_gasLimitBoundDivisor) << errinfo_got((bigint)gasLimit) << errinfo_max((bigint)_parent.gasLimit + _parent.gasLimit / c_gasLimitBoundDivisor)); // Check timestamp is after previous timestamp. if (parentHash) diff --git a/libethcore/Common.h b/libethcore/Common.h index 84459c6bf..8855bc3a7 100644 --- a/libethcore/Common.h +++ b/libethcore/Common.h @@ -136,5 +136,16 @@ private: using Handler = std::shared_ptr; +struct TransactionSkeleton +{ + bool creation = false; + Address from; + Address to; + u256 value; + bytes data; + u256 gas = UndefinedU256; + u256 gasPrice = UndefinedU256; +}; + } } diff --git a/libethcore/CommonJS.h b/libethcore/CommonJS.h index 185cd3191..0ff21afdf 100644 --- a/libethcore/CommonJS.h +++ b/libethcore/CommonJS.h @@ -50,23 +50,13 @@ std::string prettyU256(u256 _n, bool _abridged = true); } + // ethcore namespace dev { namespace eth { -struct TransactionSkeleton -{ - bool creation = false; - Address from; - Address to; - u256 value; - bytes data; - u256 gas; - u256 gasPrice; -}; - /// Convert to a block number, a bit like jsToInt, except that it correctly recognises "pending" and "latest". BlockNumber jsToBlockNumber(std::string const& _js); diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 011f0b9e0..db1a17b0a 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #if ETH_ETHASHCL || !ETH_TRUE #include #endif @@ -71,6 +72,7 @@ Ethash::WorkPackage Ethash::package(BlockInfo const& _bi) ret.boundary = _bi.boundary(); ret.headerHash = _bi.headerHash(WithoutNonce); ret.seedHash = _bi.seedHash(); + ret.blockNumber = (uint64_t) _bi.number; return ret; } @@ -87,10 +89,10 @@ bool Ethash::preVerify(BlockInfo const& _header) h256 boundary = u256((bigint(1) << 256) / _header.difficulty); return !!ethash_quick_check_difficulty( - _header.headerHash(WithoutNonce).data(), + (ethash_h256_t const*)_header.headerHash(WithoutNonce).data(), (uint64_t)(u64)_header.nonce, - _header.mixHash.data(), - boundary.data()); + (ethash_h256_t const*)_header.mixHash.data(), + (ethash_h256_t const*)boundary.data()); } bool Ethash::verify(BlockInfo const& _header) @@ -133,17 +135,14 @@ void Ethash::CPUMiner::workLoop() WorkPackage w = work(); - auto p = EthashAux::params(w.seedHash); - auto dag = EthashAux::full(w.seedHash); - auto dagPointer = dag->data.data(); - uint8_t const* headerHashPointer = w.headerHash.data(); + auto dag = EthashAux::full(w.blockNumber); h256 boundary = w.boundary; unsigned hashCount = 1; for (; !shouldStop(); tryNonce++, hashCount++) { - ethash_compute_full(ðashReturn, dagPointer, &p, headerHashPointer, tryNonce); - h256 value = h256(ethashReturn.result, h256::ConstructFromPointer); - if (value <= boundary && submitProof(Solution{(Nonce)(u64)tryNonce, h256(ethashReturn.mix_hash, h256::ConstructFromPointer)})) + ethashReturn = ethash_full_compute(dag->full, *(ethash_h256_t*)w.headerHash.data(), tryNonce); + h256 value = h256((uint8_t*)ðashReturn.result, h256::ConstructFromPointer); + if (value <= boundary && submitProof(Solution{(Nonce)(u64)tryNonce, h256((uint8_t*)ðashReturn.mix_hash, h256::ConstructFromPointer)})) break; if (!(hashCount % 1000)) accumulateHashes(1000); @@ -285,7 +284,7 @@ Ethash::GPUMiner::~GPUMiner() bool Ethash::GPUMiner::report(uint64_t _nonce) { Nonce n = (Nonce)(u64)_nonce; - Result r = EthashAux::eval(work().seedHash, work().headerHash, n); + Result r = EthashAux::eval(work().blockNumber, work().headerHash, n); if (r.value < work().boundary) return submitProof(Solution{n, r.mixHash}); return false; @@ -311,8 +310,9 @@ void Ethash::GPUMiner::workLoop() unsigned device = instances() > 1 ? index() : s_deviceId; - EthashAux::FullType dag = EthashAux::full(m_minerSeed); - m_miner->init(dag->data.data(), dag->data.size(), 32, s_platformId, device); + EthashAux::FullType dag = EthashAux::full(w.blockNumber); + bytesConstRef dagData = dag->data(); + m_miner->init(dagData.data(), dagData.size(), 32, s_platformId, device); } uint64_t upper64OfBoundary = (uint64_t)(u64)((u256)w.boundary >> 192); diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 9a66e9865..1fcab55de 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -66,7 +66,8 @@ public: h256 boundary; h256 headerHash; ///< When h256() means "pause until notified a new work package is available". - h256 seedHash; + h256 seedHash; /// LTODO: IS this needed now that we use the block number instead? + uint64_t blockNumber; }; static const WorkPackage NullWorkPackage; diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index 0b9af98ac..210f70c78 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -33,7 +33,9 @@ #include #include #include +#include #include "BlockInfo.h" +#include "Exceptions.h" using namespace std; using namespace chrono; using namespace dev; @@ -45,17 +47,9 @@ EthashAux::~EthashAux() { } -ethash_params EthashAux::params(BlockInfo const& _header) +uint64_t EthashAux::cacheSize(BlockInfo const& _header) { - return params((unsigned)_header.number); -} - -ethash_params EthashAux::params(unsigned _n) -{ - ethash_params p; - p.cache_size = ethash_get_cachesize(_n); - p.full_size = ethash_get_datasize(_n); - return p; + return ethash_get_cachesize((uint64_t)_header.number); } h256 EthashAux::seedHash(unsigned _number) @@ -82,27 +76,6 @@ h256 EthashAux::seedHash(unsigned _number) return get()->m_seedHashes[epoch]; } -ethash_params EthashAux::params(h256 const& _seedHash) -{ - Guard l(get()->x_epochs); - unsigned epoch = 0; - auto epochIter = get()->m_epochs.find(_seedHash); - if (epochIter == get()->m_epochs.end()) - { - // cdebug << "Searching for seedHash " << _seedHash; - for (h256 h; h != _seedHash && epoch < 2048; ++epoch, h = sha3(h), get()->m_epochs[h] = epoch) {} - if (epoch == 2048) - { - std::ostringstream error; - error << "apparent block number for " << _seedHash << " is too high; max is " << (ETHASH_EPOCH_LENGTH * 2048); - throw std::invalid_argument(error.str()); - } - } - else - epoch = epochIter->second; - return params(epoch * ETHASH_EPOCH_LENGTH); -} - void EthashAux::killCache(h256 const& _s) { RecursiveGuard l(x_this); @@ -111,114 +84,101 @@ void EthashAux::killCache(h256 const& _s) EthashAux::LightType EthashAux::light(BlockInfo const& _header) { - return light(_header.seedHash()); + return light((uint64_t)_header.number); } -EthashAux::LightType EthashAux::light(h256 const& _seedHash) +EthashAux::LightType EthashAux::light(uint64_t _blockNumber) { RecursiveGuard l(get()->x_this); - LightType ret = get()->m_lights[_seedHash]; - return ret ? ret : (get()->m_lights[_seedHash] = make_shared(_seedHash)); + h256 seedHash = EthashAux::seedHash(_blockNumber); + LightType ret = get()->m_lights[seedHash]; + return ret ? ret : (get()->m_lights[seedHash] = make_shared(_blockNumber)); } -EthashAux::LightAllocation::LightAllocation(h256 const& _seed) +EthashAux::LightAllocation::LightAllocation(uint64_t _blockNumber) { - auto p = params(_seed); - size = p.cache_size; - light = ethash_new_light(&p, _seed.data()); + light = ethash_light_new(_blockNumber); + size = ethash_get_cachesize(_blockNumber); } EthashAux::LightAllocation::~LightAllocation() { - ethash_delete_light(light); + ethash_light_delete(light); } -EthashAux::FullType EthashAux::full(BlockInfo const& _header, bytesRef _dest, bool _createIfMissing) +bytesConstRef EthashAux::LightAllocation::data() const { - return full(_header.seedHash(), _dest, _createIfMissing); + return bytesConstRef((byte const*)light->cache, size); } -EthashAux::FullType EthashAux::full(h256 const& _seedHash, bytesRef _dest, bool _createIfMissing) +EthashAux::FullAllocation::FullAllocation(ethash_light_t _light, ethash_callback_t _cb) { - RecursiveGuard l(get()->x_this); - FullType ret = get()->m_fulls[_seedHash].lock(); - if (ret && _dest) - { - assert(ret->data.size() <= _dest.size()); - ret->data.copyTo(_dest); - return FullType(); - } - if (!ret) - { - // drop our last used cache sine we're allocating another 1GB. - get()->m_lastUsedFull.reset(); + full = ethash_full_new(_light, _cb); +} - try { - boost::filesystem::create_directories(getDataDir("ethash")); - } catch (...) {} +EthashAux::FullAllocation::~FullAllocation() +{ + ethash_full_delete(full); +} - auto info = rlpList(Ethash::revision(), _seedHash); - std::string oldMemoFile = getDataDir("ethash") + "/full"; - std::string memoFile = getDataDir("ethash") + "/full-R" + toString(ETHASH_REVISION) + "-" + toHex(_seedHash.ref().cropped(0, 8)); - if (boost::filesystem::exists(oldMemoFile) && contents(oldMemoFile + ".info") == info) - { - // memofile valid - rename. - boost::filesystem::rename(oldMemoFile, memoFile); - } +bytesConstRef EthashAux::FullAllocation::data() const +{ + return bytesConstRef((byte const*)ethash_full_dag(full), size()); +} - DEV_IGNORE_EXCEPTIONS(boost::filesystem::remove(oldMemoFile)); - DEV_IGNORE_EXCEPTIONS(boost::filesystem::remove(oldMemoFile + ".info")); +EthashAux::FullType EthashAux::full(BlockInfo const& _header) +{ + return full((uint64_t) _header.number); +} - ethash_params p = params(_seedHash); - assert(!_dest || _dest.size() >= p.full_size); // must be big enough. +struct DAGChannel: public LogChannel { static const char* name(); static const int verbosity = 0; }; +const char* DAGChannel::name() { return EthGreen "DAG"; } +static int ethash_callback(unsigned int _progress) +{ + clog(DAGChannel) << "Generating DAG file. Progress: " << toString(_progress) << "%"; + return 0; +} - bytesRef r = contentsNew(memoFile, _dest); - if (!r) - { - if (!_createIfMissing) - return FullType(); - // file didn't exist. - if (_dest) - // buffer was passed in - no insertion into cache nor need to allocate - r = _dest; - else - r = bytesRef(new byte[p.full_size], p.full_size); - ethash_prep_full(r.data(), &p, light(_seedHash)->light); - writeFile(memoFile, r); - } - if (_dest) - return FullType(); - ret = make_shared(r); - get()->m_fulls[_seedHash] = ret; +EthashAux::FullType EthashAux::full(uint64_t _blockNumber) +{ + RecursiveGuard l(get()->x_this); + h256 seedHash = EthashAux::seedHash(_blockNumber); + FullType ret; + if ((ret = get()->m_fulls[seedHash].lock())) + { + get()->m_lastUsedFull = ret; + return ret; } - get()->m_lastUsedFull = ret; + ret = get()->m_lastUsedFull = make_shared(light(_blockNumber)->light, ethash_callback); + get()->m_fulls[seedHash] = ret; return ret; } -Ethash::Result EthashAux::eval(BlockInfo const& _header, Nonce const& _nonce) +Ethash::Result EthashAux::FullAllocation::compute(h256 const& _headerHash, Nonce const& _nonce) const { - return eval(_header.seedHash(), _header.headerHash(WithoutNonce), _nonce); + ethash_return_value_t r = ethash_full_compute(full, *(ethash_h256_t*)_headerHash.data(), (uint64_t)(u64)_nonce); + if (!r.success) + BOOST_THROW_EXCEPTION(DAGCreationFailure()); + return Ethash::Result{h256((uint8_t*)&r.result, h256::ConstructFromPointer), h256((uint8_t*)&r.mix_hash, h256::ConstructFromPointer)}; } -Ethash::Result EthashAux::FullAllocation::compute(h256 const& _seedHash, h256 const& _headerHash, Nonce const& _nonce) const +Ethash::Result EthashAux::LightAllocation::compute(h256 const& _headerHash, Nonce const& _nonce) const { - ethash_return_value r; - auto p = EthashAux::params(_seedHash); - ethash_compute_full(&r, data.data(), &p, _headerHash.data(), (uint64_t)(u64)_nonce); - return Ethash::Result{h256(r.result, h256::ConstructFromPointer), h256(r.mix_hash, h256::ConstructFromPointer)}; + ethash_return_value r = ethash_light_compute(light, *(ethash_h256_t*)_headerHash.data(), (uint64_t)(u64)_nonce); + if (!r.success) + BOOST_THROW_EXCEPTION(DAGCreationFailure()); + return Ethash::Result{h256((uint8_t*)&r.result, h256::ConstructFromPointer), h256((uint8_t*)&r.mix_hash, h256::ConstructFromPointer)}; } -Ethash::Result EthashAux::LightAllocation::compute(h256 const& _seedHash, h256 const& _headerHash, Nonce const& _nonce) const +Ethash::Result EthashAux::eval(BlockInfo const& _header, Nonce const& _nonce) { - ethash_return_value r; - auto p = EthashAux::params(_seedHash); - ethash_compute_light(&r, light, &p, _headerHash.data(), (uint64_t)(u64)_nonce); - return Ethash::Result{h256(r.result, h256::ConstructFromPointer), h256(r.mix_hash, h256::ConstructFromPointer)}; + return eval((uint64_t)_header.number, _header.headerHash(WithoutNonce), _nonce); } -Ethash::Result EthashAux::eval(h256 const& _seedHash, h256 const& _headerHash, Nonce const& _nonce) +Ethash::Result EthashAux::eval(uint64_t _blockNumber, h256 const& _headerHash, Nonce const& _nonce) { - if (auto dag = EthashAux::get()->full(_seedHash, bytesRef(), false)) - return dag->compute(_seedHash, _headerHash, _nonce); - return EthashAux::get()->light(_seedHash)->compute(_seedHash, _headerHash, _nonce); + h256 seedHash = EthashAux::seedHash(_blockNumber); + if (FullType dag = get()->m_fulls[seedHash].lock()) + return dag->compute(_headerHash, _nonce); + return EthashAux::get()->light(_blockNumber)->compute(_headerHash, _nonce); } diff --git a/libethcore/EthashAux.h b/libethcore/EthashAux.h index 0389697f5..48439a4b2 100644 --- a/libethcore/EthashAux.h +++ b/libethcore/EthashAux.h @@ -26,6 +26,7 @@ namespace dev { namespace eth{ + class EthashAux { public: @@ -33,39 +34,41 @@ public: static EthashAux* get() { if (!s_this) s_this = new EthashAux(); return s_this; } - struct FullAllocation - { - FullAllocation(bytesConstRef _d): data(_d) {} - ~FullAllocation() { delete [] data.data(); } - Ethash::Result compute(h256 const& _seedHash, h256 const& _headerHash, Nonce const& _nonce) const; - bytesConstRef const data; - }; - struct LightAllocation { - LightAllocation(h256 const& _seed); + LightAllocation(uint64_t _blockNumber); ~LightAllocation(); - bytesConstRef data() const { return bytesConstRef((byte const*)light, size); } - Ethash::Result compute(h256 const& _seedHash, h256 const& _headerHash, Nonce const& _nonce) const; + bytesConstRef data() const; + Ethash::Result compute(h256 const& _headerHash, Nonce const& _nonce) const; ethash_light_t light; uint64_t size; }; + struct FullAllocation + { + FullAllocation(ethash_light_t _light, ethash_callback_t _cb); + ~FullAllocation(); + Ethash::Result compute(h256 const& _headerHash, Nonce const& _nonce) const; + bytesConstRef data() const; + uint64_t size() const { return ethash_full_dag_size(full); } + ethash_full_t full; + }; + using LightType = std::shared_ptr; using FullType = std::shared_ptr; static h256 seedHash(unsigned _number); - static ethash_params params(BlockInfo const& _header); - static ethash_params params(h256 const& _seedHash); - static ethash_params params(unsigned _n); + static uint64_t cacheSize(BlockInfo const& _header); + static LightType light(BlockInfo const& _header); - static LightType light(h256 const& _seedHash); - static FullType full(BlockInfo const& _header, bytesRef _dest = bytesRef(), bool _createIfMissing = true); - static FullType full(h256 const& _header, bytesRef _dest = bytesRef(), bool _createIfMissing = true); + static LightType light(uint64_t _blockNumber); + static FullType full(BlockInfo const& _header); + static FullType full(uint64_t _blockNumber); static Ethash::Result eval(BlockInfo const& _header) { return eval(_header, _header.nonce); } static Ethash::Result eval(BlockInfo const& _header, Nonce const& _nonce); - static Ethash::Result eval(h256 const& _seedHash, h256 const& _headerHash, Nonce const& _nonce); + static Ethash::Result eval(uint64_t _blockNumber, h256 const& _headerHash, Nonce const& _nonce); + private: EthashAux() {} @@ -75,12 +78,12 @@ private: static EthashAux* s_this; RecursiveMutex x_this; - std::map> m_lights; - std::map> m_fulls; + std::unordered_map> m_lights; + std::unordered_map> m_fulls; FullType m_lastUsedFull; Mutex x_epochs; - std::map m_epochs; + std::unordered_map m_epochs; h256s m_seedHashes; }; diff --git a/libethcore/Exceptions.h b/libethcore/Exceptions.h index 3471a958f..8b73c96fe 100644 --- a/libethcore/Exceptions.h +++ b/libethcore/Exceptions.h @@ -73,6 +73,7 @@ class InvalidBlockNonce: virtual public dev::Exception {}; struct InvalidParentHash: virtual dev::Exception {}; struct InvalidNumber: virtual dev::Exception {}; struct InvalidContractAddress: virtual public dev::Exception {}; - +struct DAGCreationFailure: virtual public dev::Exception {}; +struct DAGComputeFailure: virtual public dev::Exception {}; } } diff --git a/libethereum/Account.h b/libethereum/Account.h index 2cc962baa..660dc0a4c 100644 --- a/libethereum/Account.h +++ b/libethereum/Account.h @@ -134,8 +134,8 @@ public: /// which encodes the base-state of the account's storage (upon which the storage is overlaid). h256 baseRoot() const { assert(m_storageRoot); return m_storageRoot; } - /// @returns the storage overlay as a simple map. - std::map const& storageOverlay() const { return m_storageOverlay; } + /// @returns the storage overlay as a simple hash map. + std::unordered_map const& storageOverlay() const { return m_storageOverlay; } /// Set a key/value pair in the account's storage. This actually goes into the overlay, for committing /// to the trie later. @@ -194,7 +194,7 @@ private: h256 m_codeHash = EmptySHA3; /// The map with is overlaid onto whatever storage is implied by the m_storageRoot in the trie. - std::map m_storageOverlay; + std::unordered_map m_storageOverlay; /// The associated code for this account. The SHA3 of this should be equal to m_codeHash unless m_codeHash /// equals c_contractConceptionCodeHash. diff --git a/libethereum/AccountDiff.h b/libethereum/AccountDiff.h index dd494c0a5..22107b958 100644 --- a/libethereum/AccountDiff.h +++ b/libethereum/AccountDiff.h @@ -62,7 +62,7 @@ struct AccountDiff Diff exist; ///< The account's existance; was it created/deleted or not? Diff balance; ///< The account's balance; did it alter? Diff nonce; ///< The account's nonce; did it alter? - std::map> storage; ///< The account's storage addresses; each has its own Diff. + std::unordered_map> storage; ///< The account's storage addresses; each has its own Diff. Diff code; ///< The account's code; in general this should only have changed if exist also changed. }; diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 192cff34c..f13f83588 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -456,7 +456,7 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import { // Check transactions are valid and that they result in a state equivalent to our state_root. // Get total difficulty increase and update state, checking it. - State s(_db); //, bi.coinbaseAddress + State s(_db); auto tdIncrease = s.enactOn(&_block, bi, *this, _ir); BlockLogBlooms blb; @@ -467,6 +467,7 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import br.receipts.push_back(s.receipt(i)); } s.cleanup(true); + td = pd.totalDifficulty + tdIncrease; #if ETH_TIMED_IMPORTS @@ -603,7 +604,6 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import { newLastBlockHash = bi.hash(); newLastBlockNumber = (unsigned)bi.number; - extrasBatch.Put(ldb::Slice("best"), ldb::Slice((char const*)&(bi.hash()), 32)); } clog(BlockChainNote) << " Imported and best" << td << " (#" << bi.number << "). Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << route; @@ -623,12 +623,33 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import m_blocksDB->Write(m_writeOptions, &blocksBatch); m_extrasDB->Write(m_writeOptions, &extrasBatch); - DEV_WRITE_GUARDED(x_lastBlockHash) + if (isKnown(bi.hash()) && !details(bi.hash())) { - m_lastBlockHash = newLastBlockHash; - m_lastBlockNumber = newLastBlockNumber; + clog(BlockChainDebug) << "Known block just inserted has no details."; + clog(BlockChainDebug) << "Block:" << bi; + clog(BlockChainDebug) << "DATABASE CORRUPTION: CRITICAL FAILURE"; + exit(-1); } + try { + State canary(_db, *this, bi.hash()); + } + catch (...) + { + clog(BlockChainDebug) << "Failed to initialise State object form imported block."; + clog(BlockChainDebug) << "Block:" << bi; + clog(BlockChainDebug) << "DATABASE CORRUPTION: CRITICAL FAILURE"; + exit(-1); + } + + if (m_lastBlockHash != newLastBlockHash) + DEV_WRITE_GUARDED(x_lastBlockHash) + { + m_lastBlockHash = newLastBlockHash; + m_lastBlockNumber = newLastBlockNumber; + m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&m_lastBlockHash, 32)); + } + #if ETH_PARANOIA || !ETH_TRUE checkConsistency(); #endif @@ -646,14 +667,6 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import if (!route.empty()) noteCanonChanged(); - if (isKnown(bi.hash()) && !details(bi.hash())) - { - clog(BlockChainDebug) << "Known block just inserted has no details."; - clog(BlockChainDebug) << "Block:" << bi; - clog(BlockChainDebug) << "DATABASE CORRUPTION: CRITICAL FAILURE"; - exit(-1); - } - h256s fresh; h256s dead; bool isOld = true; @@ -961,10 +974,10 @@ vector BlockChain::withBlockBloom(LogBloom const& _b, unsigned _earlie return ret; } -h256Set BlockChain::allUnclesFrom(h256 const& _parent) const +h256Hash BlockChain::allUnclesFrom(h256 const& _parent) const { // Get all uncles cited given a parent (i.e. featured as uncles/main in parent, parent + 1, ... parent + 5). - h256Set ret; + h256Hash ret; h256 p = _parent; for (unsigned i = 0; i < 6 && p != m_genesisHash; ++i, p = details(p).parent) { diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index 12e1fc785..e77369534 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -72,7 +72,7 @@ struct BlockChainWarn: public LogChannel { static const char* name(); static con struct BlockChainDebug: public LogChannel { static const char* name(); static const int verbosity = 0; }; // TODO: Move all this Genesis stuff into Genesis.h/.cpp -std::map const& genesisState(); +std::unordered_map const& genesisState(); ldb::Slice toSlice(h256 const& _h, unsigned _sub = 0); @@ -206,7 +206,7 @@ public: /// Get all blocks not allowed as uncles given a parent (i.e. featured as uncles/main in parent, parent + 1, ... parent + 5). /// @returns set including the header-hash of every parent (including @a _parent) up to and including generation +5 /// togther with all their quoted uncles. - h256Set allUnclesFrom(h256 const& _parent) const; + h256Hash allUnclesFrom(h256 const& _parent) const; /// Run through database and verify all blocks by reevaluating. /// Will call _progress with the progress in this operation first param done, second total. diff --git a/libethereum/BlockQueue.h b/libethereum/BlockQueue.h index d9cb0ed53..a4e44b390 100644 --- a/libethereum/BlockQueue.h +++ b/libethereum/BlockQueue.h @@ -106,15 +106,15 @@ private: bool invariants() const override; - mutable boost::shared_mutex m_lock; ///< General lock. - std::set m_drainingSet; ///< All blocks being imported. - std::set m_readySet; ///< All blocks ready for chain-import. - std::vector> m_ready; ///< List of blocks, in correct order, ready for chain-import. - std::set m_unknownSet; ///< Set of all blocks whose parents are not ready/in-chain. - std::multimap> m_unknown; ///< For blocks that have an unknown parent; we map their parent hash to the block stuff, and insert once the block appears. - std::set m_knownBad; ///< Set of blocks that we know will never be valid. - std::multimap> m_future;///< Set of blocks that are not yet valid. - Signal m_onReady; ///< Called when a subsequent call to import blocks will return a non-empty container. Be nice and exit fast. + mutable boost::shared_mutex m_lock; ///< General lock. + h256Hash m_drainingSet; ///< All blocks being imported. + h256Hash m_readySet; ///< All blocks ready for chain-import. + std::vector> m_ready; ///< List of blocks, in correct order, ready for chain-import. + h256Hash m_unknownSet; ///< Set of all blocks whose parents are not ready/in-chain. + std::unordered_multimap> m_unknown; ///< For blocks that have an unknown parent; we map their parent hash to the block stuff, and insert once the block appears. + h256Hash m_knownBad; ///< Set of blocks that we know will never be valid. + std::multimap> m_future; ///< Set of blocks that are not yet valid. Ordered by timestamp + Signal m_onReady; ///< Called when a subsequent call to import blocks will return a non-empty container. Be nice and exit fast. }; } diff --git a/libethereum/CachedAddressState.cpp b/libethereum/CachedAddressState.cpp index e2fadc8b5..a25017793 100644 --- a/libethereum/CachedAddressState.cpp +++ b/libethereum/CachedAddressState.cpp @@ -51,9 +51,9 @@ bytes CachedAddressState::code() const return h == EmptySHA3 ? bytes() : asBytes(m_o->lookup(h)); } -std::map CachedAddressState::storage() const +std::unordered_map CachedAddressState::storage() const { - std::map ret; + std::unordered_map ret; if (m_r) { SecureTrieDB memdb(const_cast(m_o), m_r[2].toHash()); // promise we won't alter the overlay! :) diff --git a/libethereum/CachedAddressState.h b/libethereum/CachedAddressState.h index 8a3c3a607..2a34c1b34 100644 --- a/libethereum/CachedAddressState.h +++ b/libethereum/CachedAddressState.h @@ -47,7 +47,7 @@ public: bytes code() const; // TODO: DEPRECATE. - std::map storage() const; + std::unordered_map storage() const; AccountDiff diff(CachedAddressState const& _c); diff --git a/libethereum/CanonBlockChain.cpp b/libethereum/CanonBlockChain.cpp index 2cc1d24dc..f1de7292b 100644 --- a/libethereum/CanonBlockChain.cpp +++ b/libethereum/CanonBlockChain.cpp @@ -41,9 +41,9 @@ namespace js = json_spirit; #define ETH_CATCH 1 -std::map const& dev::eth::genesisState() +std::unordered_map const& dev::eth::genesisState() { - static std::map s_ret; + static std::unordered_map s_ret; if (s_ret.empty()) { diff --git a/libethereum/CanonBlockChain.h b/libethereum/CanonBlockChain.h index 619af87eb..df4ac2d88 100644 --- a/libethereum/CanonBlockChain.h +++ b/libethereum/CanonBlockChain.h @@ -45,7 +45,7 @@ namespace eth { // TODO: Move all this Genesis stuff into Genesis.h/.cpp -std::map const& genesisState(); +std::unordered_map const& genesisState(); /** * @brief Implements the blockchain database. All data this gives is disk-backed. diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 01426527f..a43c98aa2 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -308,7 +308,7 @@ void Client::killChain() void Client::clearPending() { - h256Set changeds; + h256Hash changeds; DEV_WRITE_GUARDED(x_postMine) { if (!m_postMine.pending().size()) @@ -345,7 +345,7 @@ static S& filtersStreamOut(S& _out, T const& _fs) return _out; } -void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed, h256 _transactionHash) +void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Hash& io_changed, h256 _transactionHash) { Guard l(x_filtersWatches); for (pair& i: m_filters) @@ -363,7 +363,7 @@ void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Set& i } } -void Client::appendFromNewBlock(h256 const& _block, h256Set& io_changed) +void Client::appendFromNewBlock(h256 const& _block, h256Hash& io_changed) { // TODO: more precise check on whether the txs match. auto d = m_bc.info(_block); @@ -496,7 +496,7 @@ void Client::syncTransactionQueue() // returns TransactionReceipts, once for each transaction. cwork << "postSTATE <== TQ"; - h256Set changeds; + h256Hash changeds; TransactionReceipts newPendingReceipts; DEV_TIMED(working) DEV_WRITE_GUARDED(x_working) @@ -552,7 +552,7 @@ void Client::onChainChanged(ImportRoute const& _ir) if (auto h = m_host.lock()) h->noteNewBlocks(); - h256Set changeds; + h256Hash changeds; for (auto const& h: _ir.first) appendFromNewBlock(h, changeds); changeds.insert(ChainChangedFilter); @@ -631,7 +631,7 @@ void Client::startMining() onPostStateChanged(); } -void Client::noteChanged(h256Set const& _filters) +void Client::noteChanged(h256Hash const& _filters) { Guard l(x_filtersWatches); if (_filters.size()) diff --git a/libethereum/Client.h b/libethereum/Client.h index 946825828..674556a6e 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -228,15 +228,15 @@ protected: /// Collate the changed filters for the bloom filter of the given pending transaction. /// Insert any filters that are activated into @a o_changed. - void appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed, h256 _sha3); + void appendFromNewPending(TransactionReceipt const& _receipt, h256Hash& io_changed, h256 _sha3); /// Collate the changed filters for the hash of the given block. /// Insert any filters that are activated into @a o_changed. - void appendFromNewBlock(h256 const& _blockHash, h256Set& io_changed); + void appendFromNewBlock(h256 const& _blockHash, h256Hash& io_changed); /// Record that the set of filters @a _filters have changed. /// This doesn't actually make any callbacks, but incrememnts some counters in m_watches. - void noteChanged(h256Set const& _filters); + void noteChanged(h256Hash const& _filters); private: /// Called when Worker is starting. @@ -309,7 +309,6 @@ private: ActivityReport m_report; - // TODO!!!!!! REPLACE WITH A PROPER X-THREAD ASIO SIGNAL SYSTEM (could just be condition variables) std::condition_variable m_signalled; Mutex x_signalled; std::atomic m_syncTransactionQueue = {false}; diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index 136239cf3..cfa271cf6 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -75,17 +75,17 @@ Address ClientBase::submitTransaction(Secret _secret, u256 _endowment, bytes con } // TODO: remove try/catch, allow exceptions -ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff) +ExecutionResult ClientBase::call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff) { ExecutionResult ret; try { State temp = asOf(_blockNumber); - Address a = toAddress(_secret); - u256 n = temp.transactionsFrom(a); - Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); + u256 n = temp.transactionsFrom(_from); + Transaction t(_value, _gasPrice, _gas, _dest, _data, n); + t.forceSender(_from); if (_ff == FudgeFactor::Lenient) - temp.addBalance(a, (u256)(t.gas() * t.gasPrice() + t.value())); + temp.addBalance(_from, (u256)(t.gas() * t.gasPrice() + t.value())); ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted); } catch (...) @@ -95,19 +95,19 @@ ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, byt return ret; } -ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff) +ExecutionResult ClientBase::create(Address const& _from, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff) { ExecutionResult ret; try { State temp = asOf(_blockNumber); - Address a = toAddress(_secret); - u256 n = temp.transactionsFrom(a); + u256 n = temp.transactionsFrom(_from); // cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); - Transaction t(_value, _gasPrice, _gas, _data, n, _secret); + Transaction t(_value, _gasPrice, _gas, _data, n); + t.forceSender(_from); if (_ff == FudgeFactor::Lenient) - temp.addBalance(a, (u256)(t.gasRequired() * t.gasPrice() + t.value())); + temp.addBalance(_from, (u256)(t.gasRequired() * t.gasPrice() + t.value())); ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted); } catch (...) @@ -147,7 +147,7 @@ h256 ClientBase::codeHashAt(Address _a, BlockNumber _block) const return asOf(_block).codeHash(_a); } -map ClientBase::storageAt(Address _a, BlockNumber _block) const +unordered_map ClientBase::storageAt(Address _a, BlockNumber _block) const { return asOf(_block).storage(_a); } diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index fc0b301ad..235a6f540 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -81,13 +81,16 @@ public: /// Submits a new contract-creation transaction. /// @returns the new contract's address (assuming it all goes through). virtual Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override; + using Interface::submitTransaction; /// Makes the given call. Nothing is recorded into the state. - virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock, FudgeFactor _ff = FudgeFactor::Strict) override; + virtual ExecutionResult call(Address const& _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock, FudgeFactor _ff = FudgeFactor::Strict) override; + using Interface::call; /// Makes the given create. Nothing is recorded into the state. - virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock, FudgeFactor _ff = FudgeFactor::Strict) override; - + virtual ExecutionResult create(Address const& _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock, FudgeFactor _ff = FudgeFactor::Strict) override; + using Interface::create; + using Interface::balanceAt; using Interface::countAt; using Interface::stateAt; @@ -100,7 +103,7 @@ public: virtual u256 stateAt(Address _a, u256 _l, BlockNumber _block) const override; virtual bytes codeAt(Address _a, BlockNumber _block) const override; virtual h256 codeHashAt(Address _a, BlockNumber _block) const override; - virtual std::map storageAt(Address _a, BlockNumber _block) const override; + virtual std::unordered_map storageAt(Address _a, BlockNumber _block) const override; virtual LocalisedLogEntries logs(unsigned _watchId) const override; virtual LocalisedLogEntries logs(LogFilter const& _filter) const override; @@ -172,9 +175,9 @@ protected: TransactionQueue m_tq; ///< Maintains a list of incoming transactions not yet in a block on the blockchain. // filters - mutable Mutex x_filtersWatches; ///< Our lock. - std::map m_filters; ///< The dictionary of filters that are active. - std::map m_watches; ///< Each and every watch - these reference a filter. + mutable Mutex x_filtersWatches; ///< Our lock. + std::unordered_map m_filters; ///< The dictionary of filters that are active. + std::map m_watches; ///< Each and every watch - these reference a filter. }; }} diff --git a/libethereum/DownloadMan.cpp b/libethereum/DownloadMan.cpp index 1b73dca5b..05d0a533e 100644 --- a/libethereum/DownloadMan.cpp +++ b/libethereum/DownloadMan.cpp @@ -39,7 +39,7 @@ DownloadSub::~DownloadSub() } } -h256Set DownloadSub::nextFetch(unsigned _n) +h256Hash DownloadSub::nextFetch(unsigned _n) { Guard l(m_fetch); @@ -51,7 +51,7 @@ h256Set DownloadSub::nextFetch(unsigned _n) m_remaining.clear(); if (!m_man || m_man->chainEmpty()) - return h256Set(); + return h256Hash(); m_asked = (~(m_man->taken() + m_attempted)).lowest(_n); if (m_asked.empty()) diff --git a/libethereum/DownloadMan.h b/libethereum/DownloadMan.h index 82e0f09e2..2b41e660b 100644 --- a/libethereum/DownloadMan.h +++ b/libethereum/DownloadMan.h @@ -21,9 +21,9 @@ #pragma once -#include #include -#include +#include +#include #include #include #include @@ -46,7 +46,7 @@ public: ~DownloadSub(); /// Finished last fetch - grab the next bunch of block hashes to download. - h256Set nextFetch(unsigned _n); + h256Hash nextFetch(unsigned _n); /// Note that we've received a particular block. @returns true if we had asked for it but haven't received it yet. bool noteBlock(h256 _hash); @@ -71,8 +71,8 @@ private: DownloadMan* m_man = nullptr; mutable Mutex m_fetch; - h256Set m_remaining; - std::map m_indices; + h256Hash m_remaining; + std::unordered_map m_indices; RangeMask m_asked; RangeMask m_attempted; }; @@ -155,7 +155,7 @@ private: RangeMask m_blocksGot; mutable SharedMutex x_subs; - std::set m_subs; + std::unordered_set m_subs; }; } diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 299984a16..72ee1854d 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -21,7 +21,6 @@ #include "EthereumHost.h" -#include #include #include #include @@ -184,7 +183,7 @@ void EthereumHost::doWork() void EthereumHost::maintainTransactions() { // Send any new transactions. - map, h256s> peerTransactions; + unordered_map, h256s> peerTransactions; auto ts = m_tq.transactions(); for (auto const& i: ts) { diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index baa850b5c..d53c3cc79 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -22,9 +22,9 @@ #pragma once #include -#include +#include #include -#include +#include #include #include #include @@ -97,7 +97,7 @@ private: /// Get a bunch of needed blocks. /// Removes them from our list of needed blocks. /// @returns empty if there's no more blocks left to fetch, otherwise the blocks to fetch. - h256Set neededBlocks(h256Set const& _exclude); + h256Hash neededBlocks(h256Hash const& _exclude); /// Check to see if the network peer-state initialisation has happened. bool isInitialised() const { return (bool)m_latestBlockSent; } @@ -121,9 +121,9 @@ private: DownloadMan m_man; h256 m_latestBlockSent; - h256Set m_transactionsSent; + h256Hash m_transactionsSent; - std::set m_banned; + std::unordered_set m_banned; bool m_newTransactions = false; bool m_newBlocks = false; diff --git a/libethereum/EthereumPeer.h b/libethereum/EthereumPeer.h index 75ebab02f..54f7ad829 100644 --- a/libethereum/EthereumPeer.h +++ b/libethereum/EthereumPeer.h @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -140,9 +139,9 @@ private: bool m_requireTransactions = false; Mutex x_knownBlocks; - h256Set m_knownBlocks; ///< Blocks that the peer already knows about (that don't need to be sent to them). + h256Hash m_knownBlocks; ///< Blocks that the peer already knows about (that don't need to be sent to them). Mutex x_knownTransactions; - h256Set m_knownTransactions; ///< Transactions that the peer already knows of. + h256Hash m_knownTransactions; ///< Transactions that the peer already knows of. }; diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index 8807bcd58..1a2d180dd 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -91,8 +91,8 @@ public: State& state() const { return m_s; } private: - State& m_s; ///< A reference to the base state. - std::map m_origCache; ///< The cache of the address states (i.e. the externalities) as-was prior to the execution. + State& m_s; ///< A reference to the base state. + std::unordered_map m_origCache; ///< The cache of the address states (i.e. the externalities) as-was prior to the execution. }; } diff --git a/libethereum/Interface.h b/libethereum/Interface.h index ba68e976e..f7253ad29 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -72,17 +72,25 @@ public: /// @returns the new contract's address (assuming it all goes through). virtual Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo) = 0; + /// Submits a new contract-creation transaction. + /// @returns the new contract's address (assuming it all goes through). + Address submitTransaction(Secret const& _secret, TransactionSkeleton const& _t) { if (_t.creation) return submitTransaction(_secret, _t.value, _t.data, _t.gas, _t.gasPrice); submitTransaction(_secret, _t.value, _t.to, _t.data, _t.gas, _t.gasPrice); return Address(); } + /// Blocks until all pending transactions have been processed. virtual void flushTransactions() = 0; /// Makes the given call. Nothing is recorded into the state. - virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0; - ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, FudgeFactor _ff = FudgeFactor::Strict) { return call(_secret, _value, _dest, _data, _gas, _gasPrice, m_default, _ff); } + virtual ExecutionResult call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0; + ExecutionResult call(Address const& _from, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, FudgeFactor _ff = FudgeFactor::Strict) { return call(_from, _value, _dest, _data, _gas, _gasPrice, m_default, _ff); } + ExecutionResult call(Secret const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) { return call(toAddress(_secret), _value, _dest, _data, _gas, _gasPrice, _blockNumber, _ff); } + ExecutionResult call(Secret const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, FudgeFactor _ff = FudgeFactor::Strict) { return call(toAddress(_secret), _value, _dest, _data, _gas, _gasPrice, _ff); } /// Does the given creation. Nothing is recorded into the state. /// @returns the pair of the Address of the created contract together with its code. - virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0; - ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, FudgeFactor _ff = FudgeFactor::Strict) { return create(_secret, _value, _data, _gas, _gasPrice, m_default, _ff); } + virtual ExecutionResult create(Address const& _from, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0; + ExecutionResult create(Address const& _from, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, FudgeFactor _ff = FudgeFactor::Strict) { return create(_from, _value, _data, _gas, _gasPrice, m_default, _ff); } + ExecutionResult create(Secret const& _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) { return create(toAddress(_secret), _value, _data, _gas, _gasPrice, _blockNumber, _ff); } + ExecutionResult create(Secret const& _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, FudgeFactor _ff = FudgeFactor::Strict) { return create(toAddress(_secret), _value, _data, _gas, _gasPrice, _ff); } /// Injects the RLP-encoded transaction given by the _rlp into the transaction queue directly. virtual ImportResult injectTransaction(bytes const& _rlp) = 0; @@ -100,14 +108,14 @@ public: u256 stateAt(Address _a, u256 _l) const { return stateAt(_a, _l, m_default); } bytes codeAt(Address _a) const { return codeAt(_a, m_default); } h256 codeHashAt(Address _a) const { return codeHashAt(_a, m_default); } - std::map storageAt(Address _a) const { return storageAt(_a, m_default); } + std::unordered_map storageAt(Address _a) const { return storageAt(_a, m_default); } virtual u256 balanceAt(Address _a, BlockNumber _block) const = 0; virtual u256 countAt(Address _a, BlockNumber _block) const = 0; virtual u256 stateAt(Address _a, u256 _l, BlockNumber _block) const = 0; virtual bytes codeAt(Address _a, BlockNumber _block) const = 0; virtual h256 codeHashAt(Address _a, BlockNumber _block) const = 0; - virtual std::map storageAt(Address _a, BlockNumber _block) const = 0; + virtual std::unordered_map storageAt(Address _a, BlockNumber _block) const = 0; // [LOGS API] diff --git a/libethereum/KeyManager.cpp b/libethereum/KeyManager.cpp new file mode 100644 index 000000000..11b2cb2a6 --- /dev/null +++ b/libethereum/KeyManager.cpp @@ -0,0 +1,213 @@ +/* + 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 . +*/ +/** @file KeyManager.cpp + * @author Gav Wood + * @date 2014 + */ + +#include "KeyManager.h" +#include +#include +#include +#include +#include +#include +using namespace std; +using namespace dev; +using namespace eth; +namespace fs = boost::filesystem; + +KeyManager::KeyManager(std::string const& _keysFile): + m_keysFile(_keysFile) +{} + +KeyManager::~KeyManager() +{} + +bool KeyManager::exists() const +{ + return !contents(m_keysFile + ".salt").empty() && !contents(m_keysFile).empty(); +} + +void KeyManager::create(std::string const& _pass) +{ + m_password = asString(h256::random().asBytes()); + write(_pass, m_keysFile); +} + +bool KeyManager::load(std::string const& _pass) +{ + try { + bytes salt = contents(m_keysFile + ".salt"); + bytes encKeys = contents(m_keysFile); + m_key = h128(pbkdf2(_pass, salt, 262144, 16)); + bytes bs = decryptSymNoAuth(m_key, h128(), &encKeys); + RLP s(bs); + unsigned version = (unsigned)s[0]; + if (version == 1) + { + for (auto const& i: s[1]) + m_keyInfo[m_addrLookup[(Address)i[0]] = (h128)i[1]] = KeyInfo((h256)i[2], (std::string)i[3]); + for (auto const& i: s[2]) + m_passwordInfo[(h256)i[0]] = (std::string)i[1]; + m_password = (string)s[3]; + } + m_cachedPasswords[hashPassword(m_password)] = m_password; + return true; + } + catch (...) { + return false; + } +} + +Secret KeyManager::secret(Address const& _address, function const& _pass) const +{ + auto it = m_addrLookup.find(_address); + if (it == m_addrLookup.end()) + return Secret(); + return secret(it->second, _pass); +} + +Secret KeyManager::secret(h128 const& _uuid, function const& _pass) const +{ + return Secret(m_store.secret(_uuid, [&](){ + auto kit = m_keyInfo.find(_uuid); + if (kit != m_keyInfo.end()) + { + auto it = m_cachedPasswords.find(kit->second.passHash); + if (it != m_cachedPasswords.end()) + return it->second; + } + std::string p = _pass(); + m_cachedPasswords[hashPassword(p)] = p; + return p; + })); +} + +h128 KeyManager::uuid(Address const& _a) const +{ + auto it = m_addrLookup.find(_a); + if (it == m_addrLookup.end()) + return h128(); + return it->second; +} + +Address KeyManager::address(h128 const& _uuid) const +{ + for (auto const& i: m_addrLookup) + if (i.second == _uuid) + return i.first; + return Address(); +} + +h128 KeyManager::import(Secret const& _s, string const& _info, std::string const& _pass, string const& _passInfo) +{ + Address addr = KeyPair(_s).address(); + auto passHash = hashPassword(_pass); + m_cachedPasswords[passHash] = _pass; + m_passwordInfo[passHash] = _passInfo; + auto uuid = m_store.importSecret(_s.asBytes(), _pass); + m_keyInfo[uuid] = KeyInfo{passHash, _info}; + m_addrLookup[addr] = uuid; + write(m_keysFile); + return uuid; +} + +void KeyManager::importExisting(h128 const& _uuid, std::string const& _info, std::string const& _pass, std::string const& _passInfo) +{ + bytes key = m_store.secret(_uuid, [&](){ return _pass; }); + if (key.empty()) + return; + Address a = KeyPair(Secret(key)).address(); + auto passHash = hashPassword(_pass); + if (!m_passwordInfo.count(passHash)) + m_passwordInfo[passHash] = _passInfo; + if (!m_cachedPasswords.count(passHash)) + m_cachedPasswords[passHash] = _pass; + m_addrLookup[a] = _uuid; + m_keyInfo[_uuid].passHash = passHash; + m_keyInfo[_uuid].info = _info; + write(m_keysFile); +} + +void KeyManager::kill(Address const& _a) +{ + auto id = m_addrLookup[_a]; + m_addrLookup.erase(_a); + m_keyInfo.erase(id); + m_store.kill(id); +} + +AddressHash KeyManager::accounts() const +{ + AddressHash ret; + for (auto const& i: m_addrLookup) + if (m_keyInfo.count(i.second) > 0) + ret.insert(i.first); + return ret; +} + +std::unordered_map> KeyManager::accountDetails() const +{ + std::unordered_map> ret; + for (auto const& i: m_addrLookup) + if (m_keyInfo.count(i.second) > 0) + ret[i.first] = make_pair(m_keyInfo.at(i.second).info, m_passwordInfo.at(m_keyInfo.at(i.second).passHash)); + return ret; +} + +h256 KeyManager::hashPassword(std::string const& _pass) const +{ + // TODO SECURITY: store this a bit more securely; Scrypt perhaps? + return h256(pbkdf2(_pass, asBytes(m_password), 262144, 32)); +} + +bool KeyManager::write(std::string const& _keysFile) const +{ + if (!m_key) + return false; + write(m_key, _keysFile); + return true; +} + +void KeyManager::write(std::string const& _pass, std::string const& _keysFile) const +{ + bytes salt = h256::random().asBytes(); + writeFile(_keysFile + ".salt", salt); + auto key = h128(pbkdf2(_pass, salt, 262144, 16)); + write(key, _keysFile); +} + +void KeyManager::write(h128 const& _key, std::string const& _keysFile) const +{ + RLPStream s(4); + s << 1; + s.appendList(m_addrLookup.size()); + for (auto const& i: m_addrLookup) + if (m_keyInfo.count(i.second)) + { + auto ki = m_keyInfo.at(i.second); + s.appendList(4) << i.first << i.second << ki.passHash << ki.info; + } + s.appendList(m_passwordInfo.size()); + for (auto const& i: m_passwordInfo) + s.appendList(2) << i.first << i.second; + s.append(m_password); + + writeFile(_keysFile, encryptSymNoAuth(_key, h128(), &s.out())); + m_key = _key; +} diff --git a/libethereum/KeyManager.h b/libethereum/KeyManager.h new file mode 100644 index 000000000..38e8d8853 --- /dev/null +++ b/libethereum/KeyManager.h @@ -0,0 +1,115 @@ +/* + 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 . + */ +/** @file KeyManager.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#include +#include +#include +#include + +namespace dev +{ +namespace eth +{ +class UnknownPassword: public Exception {}; + +struct KeyInfo +{ + KeyInfo() = default; + KeyInfo(h256 const& _passHash, std::string const& _info): passHash(_passHash), info(_info) {} + h256 passHash; + std::string info; +}; + +static const auto DontKnowThrow = [](){ throw UnknownPassword(); return std::string(); }; + +// TODO: This one is specifically for Ethereum, but we can make it generic in due course. +// TODO: hidden-partition style key-store. +/** + * @brief High-level manager of keys for Ethereum. + * Usage: + * + * Call exists() to check whether there is already a database. If so, get the master password from + * the user and call load() with it. If not, get a new master password from the user (get them to type + * it twice and keep some hint around!) and call create() with it. + */ +class KeyManager +{ +public: + KeyManager(std::string const& _keysFile = getDataDir("ethereum") + "/keys.info"); + ~KeyManager(); + + void setKeysFile(std::string const& _keysFile) { m_keysFile = _keysFile; } + std::string const& keysFile() const { return m_keysFile; } + + bool exists() const; + void create(std::string const& _pass); + bool load(std::string const& _pass); + void save(std::string const& _pass) const { write(_pass, m_keysFile); } + + void notePassword(std::string const& _pass) { m_cachedPasswords[hashPassword(_pass)] = _pass; } + + AddressHash accounts() const; + std::unordered_map> accountDetails() const; + + h128 uuid(Address const& _a) const; + Address address(h128 const& _uuid) const; + + h128 import(Secret const& _s, std::string const& _info, std::string const& _pass, std::string const& _passInfo); + h128 import(Secret const& _s, std::string const& _info) { return import(_s, _info, m_password, std::string()); } + + SecretStore& store() { return m_store; } + void importExisting(h128 const& _uuid, std::string const& _info, std::string const& _pass, std::string const& _passInfo); + + Secret secret(Address const& _address, std::function const& _pass = DontKnowThrow) const; + Secret secret(h128 const& _uuid, std::function const& _pass = DontKnowThrow) const; + + void kill(h128 const& _id) { kill(address(_id)); } + void kill(Address const& _a); + +private: + h256 hashPassword(std::string const& _pass) const; + + // Only use if previously loaded ok. + // @returns false if wasn't previously loaded ok. + bool write(std::string const& _keysFile) const; + void write(std::string const& _pass, std::string const& _keysFile) const; + void write(h128 const& _key, std::string const& _keysFile) const; + + // Ethereum keys. + std::unordered_map m_addrLookup; + std::unordered_map m_keyInfo; + std::unordered_map m_passwordInfo; + + // Passwords that we're storing. + mutable std::unordered_map m_cachedPasswords; + + // The default password for keys in the keystore - protected by the master password. + std::string m_password; + + SecretStore m_store; + mutable h128 m_key; + mutable std::string m_keysFile; +}; + +} +} diff --git a/libethereum/LogFilter.h b/libethereum/LogFilter.h index 304fab317..97ff5a3b1 100644 --- a/libethereum/LogFilter.h +++ b/libethereum/LogFilter.h @@ -67,8 +67,8 @@ public: friend std::ostream& dev::eth::operator<<(std::ostream& _out, dev::eth::LogFilter const& _s); private: - AddressSet m_addresses; - std::array m_topics; + AddressHash m_addresses; + std::array m_topics; unsigned m_earliest = 0; unsigned m_latest = LatestBlock; }; diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index 0fd5cb45b..cdcb4a46a 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -81,7 +81,7 @@ static bytes identityCode(bytesConstRef _in) return _in.toBytes(); } -static const std::map c_precompiled = +static const std::unordered_map c_precompiled = { { 1, { [](bytesConstRef) -> bigint { return c_ecrecoverGas; }, ecrecoverCode }}, { 2, { [](bytesConstRef i) -> bigint { return c_sha256Gas + (i.size() + 31) / 32 * c_sha256WordGas; }, sha256Code }}, @@ -89,7 +89,7 @@ static const std::map c_precompiled = { 4, { [](bytesConstRef i) -> bigint { return c_identityGas + (i.size() + 31) / 32 * c_identityWordGas; }, identityCode }} }; -std::map const& dev::eth::precompiled() +std::unordered_map const& dev::eth::precompiled() { return c_precompiled; } diff --git a/libethereum/Precompiled.h b/libethereum/Precompiled.h index c65cd9a63..bded27386 100644 --- a/libethereum/Precompiled.h +++ b/libethereum/Precompiled.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include #include @@ -38,7 +38,7 @@ struct PrecompiledAddress }; /// Info on precompiled contract accounts baked into the protocol. -std::map const& precompiled(); +std::unordered_map const& precompiled(); } } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 83a78e1e8..50e4b26ab 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -208,9 +208,9 @@ StateDiff State::diff(State const& _c) const { StateDiff ret; - std::set
ads; - std::set
trieAds; - std::set
trieAdsD; + std::unordered_set
ads; + std::unordered_set
trieAds; + std::unordered_set
trieAdsD; auto trie = SecureTrieDB(const_cast(&m_db), rootHash()); auto trieD = SecureTrieDB(const_cast(&_c.m_db), _c.rootHash()); @@ -246,7 +246,7 @@ void State::ensureCached(Address _a, bool _requireCode, bool _forceCreate) const ensureCached(m_cache, _a, _requireCode, _forceCreate); } -void State::ensureCached(std::map& _cache, Address _a, bool _requireCode, bool _forceCreate) const +void State::ensureCached(std::unordered_map& _cache, Address _a, bool _requireCode, bool _forceCreate) const { auto it = _cache.find(_a); if (it == _cache.end()) @@ -426,10 +426,10 @@ u256 State::enactOn(bytesConstRef _block, BlockInfo const& _bi, BlockChain const return ret; } -map State::addresses() const +unordered_map State::addresses() const { #if ETH_FATDB - map ret; + unordered_map ret; for (auto i: m_cache) if (i.second.isAlive()) ret[i.first] = i.second.balance(); @@ -610,6 +610,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement if (receiptsTrie.root() != m_currentBlock.receiptsRoot) { cwarn << "Bad receipts state root."; + cwarn << "Expected: " << toString(receiptsTrie.root()) << " received: " << toString(m_currentBlock.receiptsRoot); cwarn << "Block:" << toHex(_block); cwarn << "Block RLP:" << rlp; cwarn << "Calculated: " << receiptsTrie.root(); @@ -649,9 +650,9 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement if (rlp[2].itemCount() > 2) BOOST_THROW_EXCEPTION(TooManyUncles()); - set nonces = { m_currentBlock.nonce }; + unordered_set nonces = { m_currentBlock.nonce }; vector rewarded; - set knownUncles = _bc.allUnclesFrom(m_currentBlock.parentHash); + h256Hash knownUncles = _bc.allUnclesFrom(m_currentBlock.parentHash); for (auto const& i: rlp[2]) { @@ -706,6 +707,7 @@ void State::cleanup(bool _fullCommit) { if (_fullCommit) { + paranoia("immediately before database commit", true); // Commit the new trie to disk. @@ -805,7 +807,7 @@ void State::commitToMine(BlockChain const& _bc) { // Find great-uncles (or second-cousins or whatever they are) - children of great-grandparents, great-great-grandparents... that were not already uncles in previous generations. // cout << "Checking " << m_previousBlock.hash << ", parent=" << m_previousBlock.parentHash << endl; - set knownUncles = _bc.allUnclesFrom(m_currentBlock.parentHash); + h256Hash knownUncles = _bc.allUnclesFrom(m_currentBlock.parentHash); auto p = m_previousBlock.parentHash; for (unsigned gen = 0; gen < 6 && p != _bc.genesisHash() && unclesCount < 2; ++gen, p = _bc.details(p).parent) { @@ -1016,9 +1018,9 @@ u256 State::storage(Address _id, u256 _memory) const return ret; } -map State::storage(Address _id) const +unordered_map State::storage(Address _id) const { - map ret; + unordered_map ret; ensureCached(_id, false, false); auto it = m_cache.find(_id); diff --git a/libethereum/State.h b/libethereum/State.h index e3468c24c..a11812c6f 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -22,7 +22,6 @@ #pragma once #include -#include #include #include #include @@ -50,7 +49,7 @@ class BlockChain; class State; struct StateChat: public LogChannel { static const char* name(); static const int verbosity = 4; }; -struct StateTrace: public LogChannel { static const char* name(); static const int verbosity = 7; }; +struct StateTrace: public LogChannel { static const char* name(); static const int verbosity = 5; }; struct StateDetail: public LogChannel { static const char* name(); static const int verbosity = 14; }; struct StateSafeExceptions: public LogChannel { static const char* name(); static const int verbosity = 21; }; @@ -142,7 +141,7 @@ public: /// @returns the set containing all addresses currently in use in Ethereum. /// @throws InterfaceNotSupported if compiled without ETH_FATDB. - std::map addresses() const; + std::unordered_map addresses() const; /// Get the header information on the present block. BlockInfo const& info() const { return m_currentBlock; } @@ -238,8 +237,8 @@ public: /// Get the storage of an account. /// @note This is expensive. Don't use it unless you need to. - /// @returns std::map if no account exists at that address. - std::map storage(Address _contract) const; + /// @returns std::unordered_map if no account exists at that address. + std::unordered_map storage(Address _contract) const; /// Get the code of an account. /// @returns bytes() if no account exists at that address. @@ -263,7 +262,7 @@ public: Transactions const& pending() const { return m_transactions; } /// Get the list of hashes of pending transactions. - h256Set const& pendingHashes() const { return m_transactionSet; } + h256Hash const& pendingHashes() const { return m_transactionSet; } /// Get the transaction receipt for the transaction of the given index. TransactionReceipt const& receipt(unsigned _i) const { return m_receipts[_i]; } @@ -334,7 +333,7 @@ private: void ensureCached(Address _a, bool _requireCode, bool _forceCreate) const; /// Retrieve all information about a given address into a cache. - void ensureCached(std::map& _cache, Address _a, bool _requireCode, bool _forceCreate) const; + void ensureCached(std::unordered_map& _cache, Address _a, bool _requireCode, bool _forceCreate) const; /// Execute the given block, assuming it corresponds to m_currentBlock. /// Throws on failure. @@ -355,10 +354,10 @@ private: SecureTrieDB m_state; ///< Our state tree, as an OverlayDB DB. Transactions m_transactions; ///< The current list of transactions that we've included in the state. TransactionReceipts m_receipts; ///< The corresponding list of transaction receipts. - std::set m_transactionSet; ///< The set of transaction hashes that we've included in the state. + h256Hash m_transactionSet; ///< The set of transaction hashes that we've included in the state. OverlayDB m_lastTx; - mutable std::map m_cache; ///< Our address cache. This stores the states of each address that has (or at least might have) been changed. + mutable std::unordered_map m_cache; ///< Our address cache. This stores the states of each address that has (or at least might have) been changed. BlockInfo m_previousBlock; ///< The previous block's information. BlockInfo m_currentBlock; ///< The current block's information. @@ -380,7 +379,7 @@ private: std::ostream& operator<<(std::ostream& _out, State const& _s); template -void commit(std::map const& _cache, DB& _db, SecureTrieDB& _state) +void commit(std::unordered_map const& _cache, DB& _db, SecureTrieDB& _state) { for (auto const& i: _cache) if (i.second.isDirty()) diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h index 2b11c52d6..78852b7b8 100644 --- a/libethereum/Transaction.h +++ b/libethereum/Transaction.h @@ -111,10 +111,10 @@ public: Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data, u256 const& _nonce, Secret const& _secret): m_type(ContractCreation), m_nonce(_nonce), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) { sign(_secret); } /// Constructs an unsigned message-call transaction. - Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data): m_type(MessageCall), m_value(_value), m_receiveAddress(_dest), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {} + Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data, u256 const& _nonce = 0): m_type(MessageCall), m_nonce(_nonce), m_value(_value), m_receiveAddress(_dest), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {} /// Constructs an unsigned contract-creation transaction. - Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data): m_type(ContractCreation), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {} + Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data, u256 const& _nonce = 0): m_type(ContractCreation), m_nonce(_nonce), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {} /// Constructs a transaction from the given RLP. explicit Transaction(bytesConstRef _rlp, CheckTransaction _checkSig); @@ -132,6 +132,8 @@ public: Address const& sender() const; /// Like sender() but will never throw. @returns a null Address if the signature is invalid. Address const& safeSender() const noexcept; + /// Force the sender to a particular value. This will result in an invalid transaction RLP. + void forceSender(Address const& _a) { m_sender = _a; } /// @returns true if transaction is non-null. explicit operator bool() const { return m_type != NullTransaction; } diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index 69e1c935f..50fcea574 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -55,7 +55,7 @@ public: void drop(h256 const& _txHash); - std::map transactions() const { ReadGuard l(m_lock); return m_current; } + std::unordered_map transactions() const { ReadGuard l(m_lock); return m_current; } std::pair items() const { ReadGuard l(m_lock); return std::make_pair(m_current.size(), m_unknown.size()); } u256 maxNonce(Address const& _a) const; @@ -72,14 +72,14 @@ private: void insertCurrent_WITH_LOCK(std::pair const& _p); bool removeCurrent_WITH_LOCK(h256 const& _txHash); - mutable SharedMutex m_lock; ///< General lock. - std::set m_known; ///< Hashes of transactions in both sets. - std::map m_current; ///< Map of SHA3(tx) to tx. - std::multimap> m_unknown; ///< For transactions that have a future nonce; we map their sender address to the tx stuff, and insert once the sender has a valid TX. - std::map> m_callbacks; ///< Called once. - std::set m_dropped; ///< Transactions that have previously been dropped. - std::multimap m_senders; ///< Mapping from the sender address to the transaction hash; useful for determining the nonce of a given sender. - Signal m_onReady; ///< Called when a subsequent call to import transactions will return a non-empty container. Be nice and exit fast. + mutable SharedMutex m_lock; ///< General lock. + h256Hash m_known; ///< Hashes of transactions in both sets. + std::unordered_map m_current; ///< Map of SHA3(tx) to tx. + std::unordered_multimap> m_unknown; ///< For transactions that have a future nonce; we map their sender address to the tx stuff, and insert once the sender has a valid TX. + std::unordered_map> m_callbacks; ///< Called once. + h256Hash m_dropped; ///< Transactions that have previously been dropped. + std::multimap m_senders; ///< Mapping from the sender address to the transaction hash; useful for determining the nonce of a given sender. + Signal m_onReady; ///< Called when a subsequent call to import transactions will return a non-empty container. Be nice and exit fast. }; } diff --git a/libethereum/TransactionReceipt.h b/libethereum/TransactionReceipt.h index 1e0663054..0a0b154f4 100644 --- a/libethereum/TransactionReceipt.h +++ b/libethereum/TransactionReceipt.h @@ -22,7 +22,6 @@ #pragma once #include -#include #include #include #include diff --git a/libethereumx/Ethereum.cpp b/libethereumx/Ethereum.cpp index 54b698646..8ab4243a1 100644 --- a/libethereumx/Ethereum.cpp +++ b/libethereumx/Ethereum.cpp @@ -87,7 +87,7 @@ void Ethereum::submitTransaction(Secret _secret, u256 _value, Address _dest, byt { } -bytes Ethereum::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) +bytes Ethereum::call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) { return bytes(); } diff --git a/libethereumx/Ethereum.h b/libethereumx/Ethereum.h index 15f00f4ae..0e81b8e0c 100644 --- a/libethereumx/Ethereum.h +++ b/libethereumx/Ethereum.h @@ -75,7 +75,7 @@ public: void flushTransactions(); /// Makes the given call. Nothing is recorded into the state. - bytes call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo); + bytes call(Address const& _from, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo); // Informational stuff diff --git a/libevm/VMFactory.h b/libevm/VMFactory.h index 777bb8cd1..d50b1aa3b 100644 --- a/libevm/VMFactory.h +++ b/libevm/VMFactory.h @@ -27,7 +27,7 @@ enum class VMKind { Interpreter, JIT, - Smart, + Smart }; class VMFactory diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 6cc09a4bc..9530ded49 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -304,9 +304,6 @@ Assembly& Assembly::optimise(bool _enable) { if (!_enable) return *this; - std::vector>> rules; - // jump to next instruction - rules.push_back({ { PushTag, Instruction::JUMP, Tag }, [](AssemblyItemsConstRef m) -> AssemblyItems { if (m[0].data() == m[2].data()) return {m[2]}; else return m.toVector(); }}); unsigned total = 0; for (unsigned count = 1; count > 0; total += count) @@ -314,10 +311,17 @@ Assembly& Assembly::optimise(bool _enable) copt << toString(*this); count = 0; + //@todo CFG interface should be a generator, that returns an item and a pointer to a + // knownstate, which has to replace the current state if it is not null. + // Feed these items to the CSE, but also store them and replace the stored version + // if the items generated by the CSE are shorter. (or even use less gas?) copt << "Performing control flow analysis..."; { ControlFlowGraph cfg(m_items); - AssemblyItems optItems = cfg.optimisedItems(); + AssemblyItems optItems; + for (BasicBlock const& block: cfg.optimisedBlocks()) + copy(m_items.begin() + block.begin, m_items.begin() + block.end, + back_inserter(optItems)); if (optItems.size() < m_items.size()) { copt << "Old size: " << m_items.size() << ", new size: " << optItems.size(); @@ -329,7 +333,9 @@ Assembly& Assembly::optimise(bool _enable) copt << "Performing common subexpression elimination..."; for (auto iter = m_items.begin(); iter != m_items.end();) { - CommonSubexpressionEliminator eliminator; + //@todo use only a single state / expression classes instance. + KnownState state(make_shared()); + CommonSubexpressionEliminator eliminator(state); auto orig = iter; iter = eliminator.feedItems(iter, m_items.end()); AssemblyItems optItems; diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index 63524d6f3..4b85eba40 100644 --- a/libevmasm/CommonSubexpressionEliminator.cpp +++ b/libevmasm/CommonSubexpressionEliminator.cpp @@ -37,18 +37,19 @@ vector CommonSubexpressionEliminator::getOptimizedItems() map initialStackContents; map targetStackContents; - int minHeight = m_stackHeight + 1; - if (!m_stackElements.empty()) - minHeight = min(minHeight, m_stackElements.begin()->first); - for (int height = minHeight; height <= 0; ++height) - initialStackContents[height] = initialStackElement(height, SourceLocation()); - for (int height = minHeight; height <= m_stackHeight; ++height) - targetStackContents[height] = stackElement(height, SourceLocation()); + int minHeight = m_state.stackHeight() + 1; + if (!m_state.stackElements().empty()) + minHeight = min(minHeight, m_state.stackElements().begin()->first); + for (int height = minHeight; height <= m_initialState.stackHeight(); ++height) + initialStackContents[height] = m_initialState.stackElement(height, SourceLocation()); + for (int height = minHeight; height <= m_state.stackHeight(); ++height) + targetStackContents[height] = m_state.stackElement(height, SourceLocation()); // Debug info: //stream(cout, initialStackContents, targetStackContents); - AssemblyItems items = CSECodeGenerator(m_expressionClasses, m_storeOperations).generateCode( + AssemblyItems items = CSECodeGenerator(m_state.expressionClasses(), m_storeOperations).generateCode( + m_initialState.stackHeight(), initialStackContents, targetStackContents ); @@ -57,103 +58,11 @@ vector CommonSubexpressionEliminator::getOptimizedItems() return items; } -ostream& CommonSubexpressionEliminator::stream( - ostream& _out, - map _initialStack, - map _targetStack -) const -{ - auto streamExpressionClass = [this](ostream& _out, Id _id) - { - auto const& expr = m_expressionClasses.representative(_id); - _out << " " << dec << _id << ": " << *expr.item; - if (expr.sequenceNumber) - _out << "@" << dec << expr.sequenceNumber; - _out << "("; - for (Id arg: expr.arguments) - _out << dec << arg << ","; - _out << ")" << endl; - }; - - _out << "Optimizer analysis:" << endl; - _out << "Final stack height: " << dec << m_stackHeight << endl; - _out << "Equivalence classes: " << endl; - for (Id eqClass = 0; eqClass < m_expressionClasses.size(); ++eqClass) - streamExpressionClass(_out, eqClass); - - _out << "Initial stack: " << endl; - for (auto const& it: _initialStack) - { - _out << " " << dec << it.first << ": "; - streamExpressionClass(_out, it.second); - } - _out << "Target stack: " << endl; - for (auto const& it: _targetStack) - { - _out << " " << dec << it.first << ": "; - streamExpressionClass(_out, it.second); - } - - return _out; -} - void CommonSubexpressionEliminator::feedItem(AssemblyItem const& _item, bool _copyItem) { - if (_item.type() != Operation) - { - assertThrow(_item.deposit() == 1, InvalidDeposit, ""); - setStackElement(++m_stackHeight, m_expressionClasses.find(_item, {}, _copyItem)); - } - else - { - Instruction instruction = _item.instruction(); - InstructionInfo info = instructionInfo(instruction); - if (SemanticInformation::isDupInstruction(_item)) - setStackElement( - m_stackHeight + 1, - stackElement( - m_stackHeight - int(instruction) + int(Instruction::DUP1), - _item.getLocation() - ) - ); - else if (SemanticInformation::isSwapInstruction(_item)) - swapStackElements( - m_stackHeight, - m_stackHeight - 1 - int(instruction) + int(Instruction::SWAP1), - _item.getLocation() - ); - else if (instruction != Instruction::POP) - { - vector arguments(info.args); - for (int i = 0; i < info.args; ++i) - arguments[i] = stackElement(m_stackHeight - i, _item.getLocation()); - if (_item.instruction() == Instruction::SSTORE) - storeInStorage(arguments[0], arguments[1], _item.getLocation()); - else if (_item.instruction() == Instruction::SLOAD) - setStackElement( - m_stackHeight + _item.deposit(), - loadFromStorage(arguments[0], _item.getLocation()) - ); - else if (_item.instruction() == Instruction::MSTORE) - storeInMemory(arguments[0], arguments[1], _item.getLocation()); - else if (_item.instruction() == Instruction::MLOAD) - setStackElement( - m_stackHeight + _item.deposit(), - loadFromMemory(arguments[0], _item.getLocation()) - ); - else if (_item.instruction() == Instruction::SHA3) - setStackElement( - m_stackHeight + _item.deposit(), - applySha3(arguments.at(0), arguments.at(1), _item.getLocation()) - ); - else - setStackElement( - m_stackHeight + _item.deposit(), - m_expressionClasses.find(_item, arguments, _copyItem) - ); - } - m_stackHeight += _item.deposit(); - } + StoreOperation op = m_state.feedItem(_item, _copyItem); + if (op.isValid()) + m_storeOperations.push_back(op); } void CommonSubexpressionEliminator::optimizeBreakingItem() @@ -164,20 +73,20 @@ void CommonSubexpressionEliminator::optimizeBreakingItem() SourceLocation const& location = m_breakingItem->getLocation(); AssemblyItem::JumpType jumpType = m_breakingItem->getJumpType(); - Id condition = stackElement(m_stackHeight - 1, location); - Id zero = m_expressionClasses.find(u256(0)); - if (m_expressionClasses.knownToBeDifferent(condition, zero)) + Id condition = m_state.stackElement(m_state.stackHeight() - 1, location); + Id zero = m_state.expressionClasses().find(u256(0)); + if (m_state.expressionClasses().knownToBeDifferent(condition, zero)) { feedItem(AssemblyItem(Instruction::SWAP1, location), true); feedItem(AssemblyItem(Instruction::POP, location), true); AssemblyItem item(Instruction::JUMP, location); item.setJumpType(jumpType); - m_breakingItem = m_expressionClasses.storeItem(item); + m_breakingItem = m_state.expressionClasses().storeItem(item); return; } - Id negatedCondition = m_expressionClasses.find(Instruction::ISZERO, {condition}); - if (m_expressionClasses.knownToBeDifferent(negatedCondition, zero)) + Id negatedCondition = m_state.expressionClasses().find(Instruction::ISZERO, {condition}); + if (m_state.expressionClasses().knownToBeDifferent(negatedCondition, zero)) { AssemblyItem it(Instruction::POP, location); feedItem(it, true); @@ -186,148 +95,6 @@ void CommonSubexpressionEliminator::optimizeBreakingItem() } } -void CommonSubexpressionEliminator::setStackElement(int _stackHeight, Id _class) -{ - m_stackElements[_stackHeight] = _class; -} - -void CommonSubexpressionEliminator::swapStackElements( - int _stackHeightA, - int _stackHeightB, - SourceLocation const& _location -) -{ - assertThrow(_stackHeightA != _stackHeightB, OptimizerException, "Swap on same stack elements."); - // ensure they are created - stackElement(_stackHeightA, _location); - stackElement(_stackHeightB, _location); - - swap(m_stackElements[_stackHeightA], m_stackElements[_stackHeightB]); -} - -ExpressionClasses::Id CommonSubexpressionEliminator::stackElement( - int _stackHeight, - SourceLocation const& _location -) -{ - if (m_stackElements.count(_stackHeight)) - return m_stackElements.at(_stackHeight); - // Stack element not found (not assigned yet), create new equivalence class. - return m_stackElements[_stackHeight] = initialStackElement(_stackHeight, _location); -} - -ExpressionClasses::Id CommonSubexpressionEliminator::initialStackElement( - int _stackHeight, - SourceLocation const& _location -) -{ - assertThrow(_stackHeight <= 0, OptimizerException, "Initial stack element of positive height requested."); - assertThrow(_stackHeight > -16, StackTooDeepException, ""); - // This is a special assembly item that refers to elements pre-existing on the initial stack. - return m_expressionClasses.find(AssemblyItem(dupInstruction(1 - _stackHeight), _location)); -} - -void CommonSubexpressionEliminator::storeInStorage(Id _slot, Id _value, SourceLocation const& _location) -{ - if (m_storageContent.count(_slot) && m_storageContent[_slot] == _value) - // do not execute the storage if we know that the value is already there - return; - m_sequenceNumber++; - decltype(m_storageContent) storageContents; - // Copy over all values (i.e. retain knowledge about them) where we know that this store - // operation will not destroy the knowledge. Specifically, we copy storage locations we know - // are different from _slot or locations where we know that the stored value is equal to _value. - for (auto const& storageItem: m_storageContent) - if (m_expressionClasses.knownToBeDifferent(storageItem.first, _slot) || storageItem.second == _value) - storageContents.insert(storageItem); - m_storageContent = move(storageContents); - - AssemblyItem item(Instruction::SSTORE, _location); - Id id = m_expressionClasses.find(item, {_slot, _value}, true, m_sequenceNumber); - m_storeOperations.push_back(StoreOperation(StoreOperation::Storage, _slot, m_sequenceNumber, id)); - m_storageContent[_slot] = _value; - // increment a second time so that we get unique sequence numbers for writes - m_sequenceNumber++; -} - -ExpressionClasses::Id CommonSubexpressionEliminator::loadFromStorage(Id _slot, SourceLocation const& _location) -{ - if (m_storageContent.count(_slot)) - return m_storageContent.at(_slot); - - AssemblyItem item(Instruction::SLOAD, _location); - return m_storageContent[_slot] = m_expressionClasses.find(item, {_slot}, true, m_sequenceNumber); -} - -void CommonSubexpressionEliminator::storeInMemory(Id _slot, Id _value, SourceLocation const& _location) -{ - if (m_memoryContent.count(_slot) && m_memoryContent[_slot] == _value) - // do not execute the store if we know that the value is already there - return; - m_sequenceNumber++; - decltype(m_memoryContent) memoryContents; - // copy over values at points where we know that they are different from _slot by at least 32 - for (auto const& memoryItem: m_memoryContent) - if (m_expressionClasses.knownToBeDifferentBy32(memoryItem.first, _slot)) - memoryContents.insert(memoryItem); - m_memoryContent = move(memoryContents); - - AssemblyItem item(Instruction::MSTORE, _location); - Id id = m_expressionClasses.find(item, {_slot, _value}, true, m_sequenceNumber); - m_storeOperations.push_back(StoreOperation(StoreOperation::Memory, _slot, m_sequenceNumber, id)); - m_memoryContent[_slot] = _value; - // increment a second time so that we get unique sequence numbers for writes - m_sequenceNumber++; -} - -ExpressionClasses::Id CommonSubexpressionEliminator::loadFromMemory(Id _slot, SourceLocation const& _location) -{ - if (m_memoryContent.count(_slot)) - return m_memoryContent.at(_slot); - - AssemblyItem item(Instruction::MLOAD, _location); - return m_memoryContent[_slot] = m_expressionClasses.find(item, {_slot}, true, m_sequenceNumber); -} - -CommonSubexpressionEliminator::Id CommonSubexpressionEliminator::applySha3( - Id _start, - Id _length, - SourceLocation const& _location -) -{ - AssemblyItem sha3Item(Instruction::SHA3, _location); - // Special logic if length is a short constant, otherwise we cannot tell. - u256 const* l = m_expressionClasses.knownConstant(_length); - // unknown or too large length - if (!l || *l > 128) - return m_expressionClasses.find(sha3Item, {_start, _length}, true, m_sequenceNumber); - - vector arguments; - for (u256 i = 0; i < *l; i += 32) - { - Id slot = m_expressionClasses.find( - AssemblyItem(Instruction::ADD, _location), - {_start, m_expressionClasses.find(i)} - ); - arguments.push_back(loadFromMemory(slot, _location)); - } - if (m_knownSha3Hashes.count(arguments)) - return m_knownSha3Hashes.at(arguments); - Id v; - // If all arguments are known constants, compute the sha3 here - if (all_of(arguments.begin(), arguments.end(), [this](Id _a) { return !!m_expressionClasses.knownConstant(_a); })) - { - bytes data; - for (Id a: arguments) - data += toBigEndian(*m_expressionClasses.knownConstant(a)); - data.resize(size_t(*l)); - v = m_expressionClasses.find(AssemblyItem(u256(sha3(data)), _location)); - } - else - v = m_expressionClasses.find(sha3Item, {_start, _length}, true, m_sequenceNumber); - return m_knownSha3Hashes[arguments] = v; -} - CSECodeGenerator::CSECodeGenerator( ExpressionClasses& _expressionClasses, vector const& _storeOperations @@ -339,10 +106,12 @@ CSECodeGenerator::CSECodeGenerator( } AssemblyItems CSECodeGenerator::generateCode( + int _initialStackHeight, map const& _initialStack, map const& _targetStackContents ) { + m_stackHeight = _initialStackHeight; m_stack = _initialStack; for (auto const& item: m_stack) if (!m_classPositions.count(item.second)) diff --git a/libevmasm/CommonSubexpressionEliminator.h b/libevmasm/CommonSubexpressionEliminator.h index 6156bc81a..6e1ba40b3 100644 --- a/libevmasm/CommonSubexpressionEliminator.h +++ b/libevmasm/CommonSubexpressionEliminator.h @@ -32,6 +32,7 @@ #include #include #include +#include namespace dev { @@ -58,20 +59,9 @@ class CommonSubexpressionEliminator { public: using Id = ExpressionClasses::Id; - struct StoreOperation - { - enum Target { Memory, Storage }; - StoreOperation( - Target _target, - Id _slot, - unsigned _sequenceNumber, - Id _expression - ): target(_target), slot(_slot), sequenceNumber(_sequenceNumber), expression(_expression) {} - Target target; - Id slot; - unsigned sequenceNumber; - Id expression; - }; + using StoreOperation = KnownState::StoreOperation; + + CommonSubexpressionEliminator(KnownState const& _state): m_initialState(_state), m_state(_state) {} /// Feeds AssemblyItems into the eliminator and @returns the iterator pointing at the first /// item that must be fed into a new instance of the eliminator. @@ -95,49 +85,11 @@ private: /// Tries to optimize the item that breaks the basic block at the end. void optimizeBreakingItem(); - /// Simplifies the given item using - /// Assigns a new equivalence class to the next sequence number of the given stack element. - void setStackElement(int _stackHeight, Id _class); - /// Swaps the given stack elements in their next sequence number. - void swapStackElements(int _stackHeightA, int _stackHeightB, SourceLocation const& _location); - /// Retrieves the current equivalence class fo the given stack element (or generates a new - /// one if it does not exist yet). - Id stackElement(int _stackHeight, SourceLocation const& _location); - /// @returns the equivalence class id of the special initial stack element at the given height - /// (must not be positive). - Id initialStackElement(int _stackHeight, SourceLocation const& _location); - - /// Increments the sequence number, deletes all storage information that might be overwritten - /// and stores the new value at the given slot. - void storeInStorage(Id _slot, Id _value, SourceLocation const& _location); - /// Retrieves the current value at the given slot in storage or creates a new special sload class. - Id loadFromStorage(Id _slot, SourceLocation const& _location); - /// Increments the sequence number, deletes all memory information that might be overwritten - /// and stores the new value at the given slot. - void storeInMemory(Id _slot, Id _value, SourceLocation const& _location); - /// Retrieves the current value at the given slot in memory or creates a new special mload class. - Id loadFromMemory(Id _slot, SourceLocation const& _location); - /// Finds or creates a new expression that applies the sha3 hash function to the contents in memory. - Id applySha3(Id _start, Id _length, SourceLocation const& _location); - - /// Current stack height, can be negative. - int m_stackHeight = 0; - /// Current stack layout, mapping stack height -> equivalence class - std::map m_stackElements; - /// Current sequence number, this is incremented with each modification to storage or memory. - unsigned m_sequenceNumber = 1; - /// Knowledge about storage content. - std::map m_storageContent; - /// Knowledge about memory content. Keys are memory addresses, note that the values overlap - /// and are not contained here if they are not completely known. - std::map m_memoryContent; - /// Keeps record of all sha3 hashes that are computed. - std::map, Id> m_knownSha3Hashes; + KnownState m_initialState; + KnownState m_state; /// Keeps information about which storage or memory slots were written to at which sequence /// number with what instruction. std::vector m_storeOperations; - /// Structure containing the classes of equivalent expressions. - ExpressionClasses m_expressionClasses; /// The item that breaks the basic block, can be nullptr. /// It is usually appended to the block but can be optimized in some cases. @@ -164,6 +116,7 @@ public: /// @param _targetStackContents final contents of the stack, by stack height relative to initial /// @note should only be called once on each object. AssemblyItems generateCode( + int _initialStackHeight, std::map const& _initialStack, std::map const& _targetStackContents ); @@ -199,7 +152,7 @@ private: AssemblyItems m_generatedItems; /// Current height of the stack relative to the start. - int m_stackHeight = 0; + int m_stackHeight; /// If (b, a) is in m_requests then b is needed to compute a. std::multimap m_neededBy; /// Current content of the stack. diff --git a/libevmasm/ControlFlowGraph.cpp b/libevmasm/ControlFlowGraph.cpp index cc4367e64..2e28317a3 100644 --- a/libevmasm/ControlFlowGraph.cpp +++ b/libevmasm/ControlFlowGraph.cpp @@ -23,9 +23,11 @@ #include #include +#include #include #include #include +#include using namespace std; using namespace dev; @@ -36,16 +38,17 @@ BlockId::BlockId(u256 const& _id): m_id(_id) assertThrow( _id < initial().m_id, OptimizerException, "Tag number too large."); } -AssemblyItems ControlFlowGraph::optimisedItems() +BasicBlocks ControlFlowGraph::optimisedBlocks() { if (m_items.empty()) - return m_items; + return BasicBlocks(); findLargestTag(); splitBlocks(); resolveNextLinks(); removeUnusedBlocks(); setPrevLinks(); + gatherKnowledge(); return rebuildCode(); } @@ -209,7 +212,78 @@ void ControlFlowGraph::setPrevLinks() } } -AssemblyItems ControlFlowGraph::rebuildCode() +void ControlFlowGraph::gatherKnowledge() +{ + // @todo actually we know that memory is filled with zeros at the beginning, + // we could make use of that. + KnownStatePointer emptyState = make_shared(); + ExpressionClasses& expr = emptyState->expressionClasses(); + bool unknownJumpEncountered = false; + + vector> workQueue({make_pair(BlockId::initial(), emptyState->copy())}); + while (!workQueue.empty()) + { + //@todo we might have to do something like incrementing the sequence number for each JUMPDEST + assertThrow(!!workQueue.back().first, OptimizerException, ""); + BasicBlock& block = m_blocks.at(workQueue.back().first); + KnownStatePointer state = workQueue.back().second; + workQueue.pop_back(); + if (block.startState) + { + state->reduceToCommonKnowledge(*block.startState); + if (*state == *block.startState) + continue; + } + + block.startState = state->copy(); + //@todo we might know the return address for the first pass, but not anymore for the second, + // -> store knowledge about tags as a union. + + // Feed all items except for the final jump yet because it will erase the target tag. + unsigned pc = block.begin; + while (pc < block.end && !SemanticInformation::altersControlFlow(m_items.at(pc))) + state->feedItem(m_items.at(pc++)); + + if ( + block.endType == BasicBlock::EndType::JUMP || + block.endType == BasicBlock::EndType::JUMPI + ) + { + assertThrow(block.begin <= pc && pc == block.end - 1, OptimizerException, ""); + //@todo in the case of JUMPI, add knowledge about the condition to the state + // (for both values of the condition) + BlockId nextBlock = expressionClassToBlockId( + state->stackElement(state->stackHeight(), SourceLocation()), + expr + ); + state->feedItem(m_items.at(pc++)); + if (nextBlock) + workQueue.push_back(make_pair(nextBlock, state->copy())); + else if (!unknownJumpEncountered) + { + // We do not know where this jump goes, so we have to reset the states of all + // JUMPDESTs. + unknownJumpEncountered = true; + for (auto const& it: m_blocks) + if (it.second.begin < it.second.end && m_items[it.second.begin].type() == Tag) + workQueue.push_back(make_pair(it.first, emptyState->copy())); + } + } + else if (block.begin <= pc && pc < block.end) + state->feedItem(m_items.at(pc++)); + assertThrow(block.end <= block.begin || pc == block.end, OptimizerException, ""); + + block.endState = state; + + if ( + block.endType == BasicBlock::EndType::HANDOVER || + block.endType == BasicBlock::EndType::JUMPI + ) + workQueue.push_back(make_pair(block.next, state->copy())); + } +} + +BasicBlocks ControlFlowGraph::rebuildCode() { map pushes; for (auto& idAndBlock: m_blocks) @@ -220,7 +294,7 @@ AssemblyItems ControlFlowGraph::rebuildCode() for (auto it: m_blocks) blocksToAdd.insert(it.first); set blocksAdded; - AssemblyItems code; + BasicBlocks blocks; for ( BlockId blockId = BlockId::initial(); @@ -233,23 +307,34 @@ AssemblyItems ControlFlowGraph::rebuildCode() blockId = m_blocks.at(blockId).prev; for (; blockId; blockId = m_blocks.at(blockId).next) { - BasicBlock const& block = m_blocks.at(blockId); + BasicBlock& block = m_blocks.at(blockId); blocksToAdd.erase(blockId); blocksAdded.insert(blockId); - auto begin = m_items.begin() + block.begin; - auto end = m_items.begin() + block.end; - if (begin == end) + if (block.begin == block.end) continue; // If block starts with unused tag, skip it. - if (previousHandedOver && !pushes[blockId] && begin->type() == Tag) - ++begin; + if (previousHandedOver && !pushes[blockId] && m_items[block.begin].type() == Tag) + ++block.begin; + if (block.begin < block.end) + blocks.push_back(block); previousHandedOver = (block.endType == BasicBlock::EndType::HANDOVER); - copy(begin, end, back_inserter(code)); } } - return code; + return blocks; +} + +BlockId ControlFlowGraph::expressionClassToBlockId( + ExpressionClasses::Id _id, + ExpressionClasses& _exprClasses +) +{ + ExpressionClasses::Expression expr = _exprClasses.representative(_id); + if (expr.item && expr.item->type() == PushTag) + return BlockId(expr.item->data()); + else + return BlockId::invalid(); } BlockId ControlFlowGraph::generateNewId() diff --git a/libevmasm/ControlFlowGraph.h b/libevmasm/ControlFlowGraph.h index 5d16df327..3366dc45f 100644 --- a/libevmasm/ControlFlowGraph.h +++ b/libevmasm/ControlFlowGraph.h @@ -24,16 +24,18 @@ #pragma once #include +#include #include #include +#include namespace dev { namespace eth { -class AssemblyItem; -using AssemblyItems = std::vector; +class KnownState; +using KnownStatePointer = std::shared_ptr; /** * Identifier for a block, coincides with the tag number of an AssemblyItem but adds a special @@ -69,32 +71,46 @@ struct BasicBlock unsigned end = 0; /// Tags pushed inside this block, with multiplicity. std::vector pushedTags; - /// ID of the block that always follows this one (either JUMP or flow into new block), - /// or BlockId::invalid() otherwise + /// ID of the block that always follows this one (either non-branching part of JUMPI or flow + /// into new block), or BlockId::invalid() otherwise BlockId next = BlockId::invalid(); - /// ID of the block that has to precede this one. + /// ID of the block that has to precede this one (because control flows into it). BlockId prev = BlockId::invalid(); enum class EndType { JUMP, JUMPI, STOP, HANDOVER }; EndType endType = EndType::HANDOVER; + + /// Knowledge about the state when this block is entered. Intersection of all possible ways + /// to enter this block. + KnownStatePointer startState; + /// Knowledge about the state at the end of this block. + KnownStatePointer endState; }; +using BasicBlocks = std::vector; + class ControlFlowGraph { public: /// Initializes the control flow graph. /// @a _items has to persist across the usage of this class. ControlFlowGraph(AssemblyItems const& _items): m_items(_items) {} - /// @returns the collection of optimised items, should be called only once. - AssemblyItems optimisedItems(); + /// @returns vector of basic blocks in the order they should be used in the final code. + /// Should be called only once. + BasicBlocks optimisedBlocks(); private: void findLargestTag(); void splitBlocks(); void resolveNextLinks(); void removeUnusedBlocks(); + void gatherKnowledge(); void setPrevLinks(); - AssemblyItems rebuildCode(); + BasicBlocks rebuildCode(); + + /// @returns the corresponding BlockId if _id is a pushed jump tag, + /// and an invalid BlockId otherwise. + BlockId expressionClassToBlockId(ExpressionClasses::Id _id, ExpressionClasses& _exprClasses); BlockId generateNewId(); diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp index 1e60a7fe8..cfbeba7fa 100644 --- a/libevmasm/ExpressionClasses.cpp +++ b/libevmasm/ExpressionClasses.cpp @@ -37,6 +37,7 @@ using namespace dev::eth; bool ExpressionClasses::Expression::operator<(ExpressionClasses::Expression const& _other) const { + assertThrow(!!item && !!_other.item, OptimizerException, ""); auto type = item->type(); auto otherType = _other.item->type(); return std::tie(type, item->data(), arguments, sequenceNumber) < @@ -56,12 +57,15 @@ ExpressionClasses::Id ExpressionClasses::find( exp.arguments = _arguments; exp.sequenceNumber = _sequenceNumber; - if (SemanticInformation::isCommutativeOperation(_item)) - sort(exp.arguments.begin(), exp.arguments.end()); + if (SemanticInformation::isDeterministic(_item)) + { + if (SemanticInformation::isCommutativeOperation(_item)) + sort(exp.arguments.begin(), exp.arguments.end()); - auto it = m_expressions.find(exp); - if (it != m_expressions.end()) - return it->id; + auto it = m_expressions.find(exp); + if (it != m_expressions.end()) + return it->id; + } if (_copyItem) exp.item = storeItem(_item); @@ -122,10 +126,16 @@ string ExpressionClasses::fullDAGToString(ExpressionClasses::Id _id) const { Expression const& expr = representative(_id); stringstream str; - str << dec << expr.id << ":" << *expr.item << "("; - for (Id arg: expr.arguments) - str << fullDAGToString(arg) << ","; - str << ")"; + str << dec << expr.id << ":"; + if (expr.item) + { + str << *expr.item << "("; + for (Id arg: expr.arguments) + str << fullDAGToString(arg) << ","; + str << ")"; + } + else + str << " UNIQUE"; return str.str(); } @@ -279,7 +289,11 @@ ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr, { static Rules rules; - if (_expr.item->type() != Operation) + if ( + !_expr.item || + _expr.item->type() != Operation || + !SemanticInformation::isDeterministic(*_expr.item) + ) return -1; for (auto const& rule: rules.rules()) @@ -337,7 +351,7 @@ void Pattern::setMatchGroup(unsigned _group, map& _ bool Pattern::matches(Expression const& _expr, ExpressionClasses const& _classes) const { - if (!matchesBaseItem(*_expr.item)) + if (!matchesBaseItem(_expr.item)) return false; if (m_matchGroup) { @@ -387,13 +401,15 @@ string Pattern::toString() const return s.str(); } -bool Pattern::matchesBaseItem(AssemblyItem const& _item) const +bool Pattern::matchesBaseItem(AssemblyItem const* _item) const { if (m_type == UndefinedItem) return true; - if (m_type != _item.type()) + if (!_item) + return false; + if (m_type != _item->type()) return false; - if (m_requireDataMatch && m_data != _item.data()) + if (m_requireDataMatch && m_data != _item->data()) return false; return true; } diff --git a/libevmasm/ExpressionClasses.h b/libevmasm/ExpressionClasses.h index 2f720f606..c83520300 100644 --- a/libevmasm/ExpressionClasses.h +++ b/libevmasm/ExpressionClasses.h @@ -50,7 +50,7 @@ public: struct Expression { Id id; - AssemblyItem const* item; + AssemblyItem const* item = nullptr; Ids arguments; unsigned sequenceNumber; ///< Storage modification sequence, only used for SLOAD/SSTORE instructions. /// Behaves as if this was a tuple of (item->type(), item->data(), arguments, sequenceNumber). @@ -149,7 +149,7 @@ public: std::string toString() const; private: - bool matchesBaseItem(AssemblyItem const& _item) const; + bool matchesBaseItem(AssemblyItem const* _item) const; Expression const& matchGroupValue() const; AssemblyItemType m_type; diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp new file mode 100644 index 000000000..41ac4802b --- /dev/null +++ b/libevmasm/KnownState.cpp @@ -0,0 +1,326 @@ +/* + 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 . +*/ +/** + * @file KnownState.cpp + * @author Christian + * @date 2015 + * Contains knowledge about the state of the virtual machine at a specific instruction. + */ + +#include "KnownState.h" +#include +#include +#include + +using namespace std; +using namespace dev; +using namespace dev::eth; + +ostream& KnownState::stream(ostream& _out) const +{ + auto streamExpressionClass = [this](ostream& _out, Id _id) + { + auto const& expr = m_expressionClasses->representative(_id); + _out << " " << dec << _id << ": "; + if (!expr.item) + _out << " no item"; + else if (expr.item->type() == UndefinedItem) + _out << " unknown " << int(expr.item->data()); + else + _out << *expr.item; + if (expr.sequenceNumber) + _out << "@" << dec << expr.sequenceNumber; + _out << "("; + for (Id arg: expr.arguments) + _out << dec << arg << ","; + _out << ")" << endl; + }; + + _out << "=== State ===" << endl; + _out << "Stack height: " << dec << m_stackHeight << endl; + _out << "Equivalence classes: " << endl; + for (Id eqClass = 0; eqClass < m_expressionClasses->size(); ++eqClass) + streamExpressionClass(_out, eqClass); + + _out << "Stack: " << endl; + for (auto const& it: m_stackElements) + { + _out << " " << dec << it.first << ": "; + streamExpressionClass(_out, it.second); + } + _out << "Storage: " << endl; + for (auto const& it: m_storageContent) + { + _out << " "; + streamExpressionClass(_out, it.first); + _out << ": "; + streamExpressionClass(_out, it.second); + } + _out << "Memory: " << endl; + for (auto const& it: m_memoryContent) + { + _out << " "; + streamExpressionClass(_out, it.first); + _out << ": "; + streamExpressionClass(_out, it.second); + } + + return _out; +} + +KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool _copyItem) +{ + StoreOperation op; + if (_item.type() == Tag) + { + // can be ignored + } + else if (_item.type() != Operation) + { + assertThrow(_item.deposit() == 1, InvalidDeposit, ""); + setStackElement(++m_stackHeight, m_expressionClasses->find(_item, {}, _copyItem)); + } + else + { + Instruction instruction = _item.instruction(); + InstructionInfo info = instructionInfo(instruction); + if (SemanticInformation::isDupInstruction(_item)) + setStackElement( + m_stackHeight + 1, + stackElement( + m_stackHeight - int(instruction) + int(Instruction::DUP1), + _item.getLocation() + ) + ); + else if (SemanticInformation::isSwapInstruction(_item)) + swapStackElements( + m_stackHeight, + m_stackHeight - 1 - int(instruction) + int(Instruction::SWAP1), + _item.getLocation() + ); + else if (instruction != Instruction::POP) + { + vector arguments(info.args); + for (int i = 0; i < info.args; ++i) + arguments[i] = stackElement(m_stackHeight - i, _item.getLocation()); + + if (_item.instruction() == Instruction::SSTORE) + op = storeInStorage(arguments[0], arguments[1], _item.getLocation()); + else if (_item.instruction() == Instruction::SLOAD) + setStackElement( + m_stackHeight + _item.deposit(), + loadFromStorage(arguments[0], _item.getLocation()) + ); + else if (_item.instruction() == Instruction::MSTORE) + op = storeInMemory(arguments[0], arguments[1], _item.getLocation()); + else if (_item.instruction() == Instruction::MLOAD) + setStackElement( + m_stackHeight + _item.deposit(), + loadFromMemory(arguments[0], _item.getLocation()) + ); + else if (_item.instruction() == Instruction::SHA3) + setStackElement( + m_stackHeight + _item.deposit(), + applySha3(arguments.at(0), arguments.at(1), _item.getLocation()) + ); + else + { + if (SemanticInformation::invalidatesMemory(_item.instruction())) + resetMemory(); + if (SemanticInformation::invalidatesStorage(_item.instruction())) + resetStorage(); + assertThrow(info.ret <= 1, InvalidDeposit, ""); + if (info.ret == 1) + setStackElement( + m_stackHeight + _item.deposit(), + m_expressionClasses->find(_item, arguments, _copyItem) + ); + } + } + m_stackElements.erase( + m_stackElements.upper_bound(m_stackHeight + _item.deposit()), + m_stackElements.end() + ); + m_stackHeight += _item.deposit(); + } + return op; +} + +void KnownState::reduceToCommonKnowledge(KnownState const& /*_other*/) +{ + //@todo + *this = KnownState(m_expressionClasses); +} + +bool KnownState::operator==(const KnownState& _other) const +{ + //@todo + return ( + m_stackElements.empty() && + _other.m_stackElements.empty() && + m_storageContent.empty() && + _other.m_storageContent.empty() && + m_memoryContent.empty() && + _other.m_memoryContent.empty() + ); +} + +ExpressionClasses::Id KnownState::stackElement(int _stackHeight, SourceLocation const& _location) +{ + if (m_stackElements.count(_stackHeight)) + return m_stackElements.at(_stackHeight); + // Stack element not found (not assigned yet), create new unknown equivalence class. + //@todo check that we do not infer incorrect equivalences when the stack is cleared partially + //in between. + return m_stackElements[_stackHeight] = initialStackElement(_stackHeight, _location); +} + +ExpressionClasses::Id KnownState::initialStackElement( + int _stackHeight, + SourceLocation const& _location +) +{ + // This is a special assembly item that refers to elements pre-existing on the initial stack. + return m_expressionClasses->find(AssemblyItem(UndefinedItem, u256(_stackHeight), _location)); +} + +void KnownState::setStackElement(int _stackHeight, Id _class) +{ + m_stackElements[_stackHeight] = _class; +} + +void KnownState::swapStackElements( + int _stackHeightA, + int _stackHeightB, + SourceLocation const& _location +) +{ + assertThrow(_stackHeightA != _stackHeightB, OptimizerException, "Swap on same stack elements."); + // ensure they are created + stackElement(_stackHeightA, _location); + stackElement(_stackHeightB, _location); + + swap(m_stackElements[_stackHeightA], m_stackElements[_stackHeightB]); +} + +KnownState::StoreOperation KnownState::storeInStorage( + Id _slot, + Id _value, + SourceLocation const& _location) +{ + if (m_storageContent.count(_slot) && m_storageContent[_slot] == _value) + // do not execute the storage if we know that the value is already there + return StoreOperation(); + m_sequenceNumber++; + decltype(m_storageContent) storageContents; + // Copy over all values (i.e. retain knowledge about them) where we know that this store + // operation will not destroy the knowledge. Specifically, we copy storage locations we know + // are different from _slot or locations where we know that the stored value is equal to _value. + for (auto const& storageItem: m_storageContent) + if (m_expressionClasses->knownToBeDifferent(storageItem.first, _slot) || storageItem.second == _value) + storageContents.insert(storageItem); + m_storageContent = move(storageContents); + + AssemblyItem item(Instruction::SSTORE, _location); + Id id = m_expressionClasses->find(item, {_slot, _value}, true, m_sequenceNumber); + StoreOperation operation(StoreOperation::Storage, _slot, m_sequenceNumber, id); + m_storageContent[_slot] = _value; + // increment a second time so that we get unique sequence numbers for writes + m_sequenceNumber++; + + return operation; +} + +ExpressionClasses::Id KnownState::loadFromStorage(Id _slot, SourceLocation const& _location) +{ + if (m_storageContent.count(_slot)) + return m_storageContent.at(_slot); + + AssemblyItem item(Instruction::SLOAD, _location); + return m_storageContent[_slot] = m_expressionClasses->find(item, {_slot}, true, m_sequenceNumber); +} + +KnownState::StoreOperation KnownState::storeInMemory(Id _slot, Id _value, SourceLocation const& _location) +{ + if (m_memoryContent.count(_slot) && m_memoryContent[_slot] == _value) + // do not execute the store if we know that the value is already there + return StoreOperation(); + m_sequenceNumber++; + decltype(m_memoryContent) memoryContents; + // copy over values at points where we know that they are different from _slot by at least 32 + for (auto const& memoryItem: m_memoryContent) + if (m_expressionClasses->knownToBeDifferentBy32(memoryItem.first, _slot)) + memoryContents.insert(memoryItem); + m_memoryContent = move(memoryContents); + + AssemblyItem item(Instruction::MSTORE, _location); + Id id = m_expressionClasses->find(item, {_slot, _value}, true, m_sequenceNumber); + StoreOperation operation(StoreOperation(StoreOperation::Memory, _slot, m_sequenceNumber, id)); + m_memoryContent[_slot] = _value; + // increment a second time so that we get unique sequence numbers for writes + m_sequenceNumber++; + return operation; +} + +ExpressionClasses::Id KnownState::loadFromMemory(Id _slot, SourceLocation const& _location) +{ + if (m_memoryContent.count(_slot)) + return m_memoryContent.at(_slot); + + AssemblyItem item(Instruction::MLOAD, _location); + return m_memoryContent[_slot] = m_expressionClasses->find(item, {_slot}, true, m_sequenceNumber); +} + +KnownState::Id KnownState::applySha3( + Id _start, + Id _length, + SourceLocation const& _location +) +{ + AssemblyItem sha3Item(Instruction::SHA3, _location); + // Special logic if length is a short constant, otherwise we cannot tell. + u256 const* l = m_expressionClasses->knownConstant(_length); + // unknown or too large length + if (!l || *l > 128) + return m_expressionClasses->find(sha3Item, {_start, _length}, true, m_sequenceNumber); + + vector arguments; + for (u256 i = 0; i < *l; i += 32) + { + Id slot = m_expressionClasses->find( + AssemblyItem(Instruction::ADD, _location), + {_start, m_expressionClasses->find(i)} + ); + arguments.push_back(loadFromMemory(slot, _location)); + } + if (m_knownSha3Hashes.count(arguments)) + return m_knownSha3Hashes.at(arguments); + Id v; + // If all arguments are known constants, compute the sha3 here + if (all_of(arguments.begin(), arguments.end(), [this](Id _a) { return !!m_expressionClasses->knownConstant(_a); })) + { + bytes data; + for (Id a: arguments) + data += toBigEndian(*m_expressionClasses->knownConstant(a)); + data.resize(size_t(*l)); + v = m_expressionClasses->find(AssemblyItem(u256(sha3(data)), _location)); + } + else + v = m_expressionClasses->find(sha3Item, {_start, _length}, true, m_sequenceNumber); + return m_knownSha3Hashes[arguments] = v; +} + diff --git a/libevmasm/KnownState.h b/libevmasm/KnownState.h new file mode 100644 index 000000000..f7a3dd675 --- /dev/null +++ b/libevmasm/KnownState.h @@ -0,0 +1,163 @@ +/* + 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 . +*/ +/** + * @file KnownState.h + * @author Christian + * @date 2015 + * Contains knowledge about the state of the virtual machine at a specific instruction. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace dev +{ +namespace eth +{ + +class AssemblyItem; +using AssemblyItems = std::vector; + +/** + * Class to infer and store knowledge about the state of the virtual machine at a specific + * instruction. + * + * The general workings are that for each assembly item that is fed, an equivalence class is + * derived from the operation and the equivalence class of its arguments. DUPi, SWAPi and some + * arithmetic instructions are used to infer equivalences while these classes are determined. + */ +class KnownState +{ +public: + using Id = ExpressionClasses::Id; + struct StoreOperation + { + enum Target { Invalid, Memory, Storage }; + StoreOperation(): target(Invalid), sequenceNumber(-1) {} + StoreOperation( + Target _target, + Id _slot, + unsigned _sequenceNumber, + Id _expression + ): target(_target), slot(_slot), sequenceNumber(_sequenceNumber), expression(_expression) {} + bool isValid() const { return target != Invalid; } + Target target; + Id slot; + unsigned sequenceNumber; + Id expression; + }; + + explicit KnownState( + std::shared_ptr _expressionClasses = std::make_shared() + ): m_expressionClasses(_expressionClasses) + { + } + + /// Streams debugging information to @a _out. + std::ostream& stream(std::ostream& _out) const; + + /// Feeds the item into the system for analysis. + /// @returns a possible store operation + StoreOperation feedItem(AssemblyItem const& _item, bool _copyItem = false); + + /// Resets any knowledge about storage. + void resetStorage() { m_storageContent.clear(); } + /// Resets any knowledge about storage. + void resetMemory() { m_memoryContent.clear(); } + /// Resets any knowledge about the current stack. + void resetStack() { m_stackElements.clear(); m_stackHeight = 0; } + /// Resets any knowledge. + void reset() { resetStorage(); resetMemory(); resetStack(); } + + /// Manually increments the storage and memory sequence number. + void incrementSequenceNumber() { m_sequenceNumber += 2; } + + /// Replaces the state by the intersection with _other, i.e. only equal knowledge is retained. + /// If the stack heighht is different, the smaller one is used and the stack is compared + /// relatively. + void reduceToCommonKnowledge(KnownState const& _other); + + /// @returns a shared pointer to a copy of this state. + std::shared_ptr copy() const { return std::make_shared(*this); } + + /// @returns true if the knowledge about the state of both objects is (known to be) equal. + bool operator==(KnownState const& _other) const; + + ///@todo the sequence numbers in two copies of this class should never be the same. + /// might be doable using two-dimensional sequence numbers, where the first value is incremented + /// for each copy + + /// Retrieves the current equivalence class fo the given stack element (or generates a new + /// one if it does not exist yet). + Id stackElement(int _stackHeight, SourceLocation const& _location); + /// @returns the equivalence class id of the special initial stack element at the given height. + Id initialStackElement(int _stackHeight, SourceLocation const& _location); + + int stackHeight() const { return m_stackHeight; } + std::map const& stackElements() const { return m_stackElements; } + ExpressionClasses& expressionClasses() const { return *m_expressionClasses; } + +private: + /// Assigns a new equivalence class to the next sequence number of the given stack element. + void setStackElement(int _stackHeight, Id _class); + /// Swaps the given stack elements in their next sequence number. + void swapStackElements(int _stackHeightA, int _stackHeightB, SourceLocation const& _location); + + /// Increments the sequence number, deletes all storage information that might be overwritten + /// and stores the new value at the given slot. + /// @returns the store operation, which might be invalid if storage was not modified + StoreOperation storeInStorage(Id _slot, Id _value, SourceLocation const& _location); + /// Retrieves the current value at the given slot in storage or creates a new special sload class. + Id loadFromStorage(Id _slot, SourceLocation const& _location); + /// Increments the sequence number, deletes all memory information that might be overwritten + /// and stores the new value at the given slot. + /// @returns the store operation, which might be invalid if memory was not modified + StoreOperation storeInMemory(Id _slot, Id _value, SourceLocation const& _location); + /// Retrieves the current value at the given slot in memory or creates a new special mload class. + Id loadFromMemory(Id _slot, SourceLocation const& _location); + /// Finds or creates a new expression that applies the sha3 hash function to the contents in memory. + Id applySha3(Id _start, Id _length, SourceLocation const& _location); + + /// Current stack height, can be negative. + int m_stackHeight = 0; + /// Current stack layout, mapping stack height -> equivalence class + std::map m_stackElements; + /// Current sequence number, this is incremented with each modification to storage or memory. + unsigned m_sequenceNumber = 1; + /// Knowledge about storage content. + std::map m_storageContent; + /// Knowledge about memory content. Keys are memory addresses, note that the values overlap + /// and are not contained here if they are not completely known. + std::map m_memoryContent; + /// Keeps record of all sha3 hashes that are computed. + std::map, Id> m_knownSha3Hashes; + /// Structure containing the classes of equivalent expressions. + std::shared_ptr m_expressionClasses; +}; + +} +} diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index 83d59efc7..056162b5f 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -122,3 +122,56 @@ bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) return false; } } + + +bool SemanticInformation::isDeterministic(AssemblyItem const& _item) +{ + if (_item.type() != Operation) + return true; + + switch (_item.instruction()) + { + case Instruction::CALL: + case Instruction::CALLCODE: + case Instruction::CREATE: + case Instruction::GAS: + case Instruction::PC: + case Instruction::MSIZE: // depends on previous writes and reads, not only on content + case Instruction::BALANCE: // depends on previous calls + case Instruction::EXTCODESIZE: + return false; + default: + return true; + } +} + +bool SemanticInformation::invalidatesMemory(Instruction _instruction) +{ + switch (_instruction) + { + case Instruction::CALLDATACOPY: + case Instruction::CODECOPY: + case Instruction::EXTCODECOPY: + case Instruction::MSTORE: + case Instruction::MSTORE8: + case Instruction::CALL: + case Instruction::CALLCODE: + return true; + default: + return false; + } +} + +bool SemanticInformation::invalidatesStorage(Instruction _instruction) +{ + switch (_instruction) + { + case Instruction::CALL: + case Instruction::CALLCODE: + case Instruction::CREATE: + case Instruction::SSTORE: + return true; + default: + return false; + } +} diff --git a/libevmasm/SemanticInformation.h b/libevmasm/SemanticInformation.h index 27aa6f1a4..094f45912 100644 --- a/libevmasm/SemanticInformation.h +++ b/libevmasm/SemanticInformation.h @@ -23,6 +23,7 @@ #pragma once +#include namespace dev { @@ -45,6 +46,13 @@ struct SemanticInformation static bool isSwapInstruction(AssemblyItem const& _item); static bool isJumpInstruction(AssemblyItem const& _item); static bool altersControlFlow(AssemblyItem const& _item); + /// @returns false if the value put on the stack by _item depends on anything else than + /// the information in the current block header, memory, storage or stack. + static bool isDeterministic(AssemblyItem const& _item); + /// @returns true if the given instruction modifies memory. + static bool invalidatesMemory(Instruction _instruction); + /// @returns true if the given instruction modifies storage (even indirectly). + static bool invalidatesStorage(Instruction _instruction); }; } diff --git a/libjsconsole/CMakeLists.txt b/libjsconsole/CMakeLists.txt new file mode 100644 index 000000000..e8f98de88 --- /dev/null +++ b/libjsconsole/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (${CMAKE_MAJOR_VERSION} GREATER 2) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() + +set(CMAKE_AUTOMOC OFF) + +aux_source_directory(. SRC_LIST) + +include_directories(BEFORE ${V8_INCLUDE_DIRS}) +include_directories(BEFORE ..) +include_directories(${READLINE_INCLUDE_DIRS}) +include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) + +set(EXECUTABLE jsconsole) + +file(GLOB HEADERS "*.h") + +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) + +target_link_libraries(${EXECUTABLE} jsengine) +target_link_libraries(${EXECUTABLE} devcore) +target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES}) +target_link_libraries(${EXECUTABLE} web3jsonrpc) + +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libjsconsole/JSConsole.cpp b/libjsconsole/JSConsole.cpp new file mode 100644 index 000000000..791df2de4 --- /dev/null +++ b/libjsconsole/JSConsole.cpp @@ -0,0 +1,86 @@ +/* + 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 . +*/ +/** @file JSConsole.cpp + * @author Marek Kotewicz + * @date 2015 + * Ethereum client. + */ + +#include +#include +#include +#include "JSConsole.h" +#include "JSV8Connector.h" +#include "libjsconsole/JSConsoleResources.hpp" + +// TODO! make readline optional! +#include +#include + +using namespace std; +using namespace dev; +using namespace dev::eth; + +JSConsole::JSConsole(WebThreeDirect& _web3, std::vector const& _accounts): + m_engine(), + m_printer(m_engine) +{ + m_jsonrpcConnector.reset(new JSV8Connector(m_engine)); + m_jsonrpcServer.reset(new WebThreeStubServer(*m_jsonrpcConnector.get(), _web3, _accounts)); +} + +JSConsole::~JSConsole() {} + +void JSConsole::repl() const +{ + string cmd = ""; + g_logPost = [](std::string const& a, char const*) { cout << "\r \r" << a << endl << flush; rl_forced_update_display(); }; + + bool isEmpty = true; + int openBrackets = 0; + do { + char* buff = readline(promptForIndentionLevel(openBrackets).c_str()); + isEmpty = !(buff && *buff); + if (!isEmpty) + { + cmd += string(buff); + cmd += " "; + free(buff); + int open = count(cmd.begin(), cmd.end(), '{'); + open += count(cmd.begin(), cmd.end(), '('); + int closed = count(cmd.begin(), cmd.end(), '}'); + closed += count(cmd.begin(), cmd.end(), ')'); + openBrackets = open - closed; + } + } while (openBrackets > 0); + + if (!isEmpty) + { + add_history(cmd.c_str()); + auto value = m_engine.eval(cmd.c_str()); + string result = m_printer.prettyPrint(value).cstr(); + cout << result << endl; + } +} + +std::string JSConsole::promptForIndentionLevel(int _i) const +{ + if (_i == 0) + return "> "; + + return string((_i + 1) * 2, ' '); +} diff --git a/libjsconsole/JSConsole.h b/libjsconsole/JSConsole.h new file mode 100644 index 000000000..3b65691f6 --- /dev/null +++ b/libjsconsole/JSConsole.h @@ -0,0 +1,53 @@ +/* + 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 . +*/ +/** @file JSConsole.h + * @author Marek Kotewicz + * @date 2015 + * Ethereum client. + */ + +#pragma once + +#include +#include + +class WebThreeStubServer; +namespace jsonrpc { class AbstractServerConnector; } + +namespace dev +{ +namespace eth +{ + +class JSConsole +{ +public: + JSConsole(WebThreeDirect& _web3, std::vector const& _accounts); + ~JSConsole(); + void repl() const; + +private: + std::string promptForIndentionLevel(int _i) const; + + JSV8Engine m_engine; + JSV8Printer m_printer; + std::unique_ptr m_jsonrpcServer; + std::unique_ptr m_jsonrpcConnector; +}; + +} +} diff --git a/libjsconsole/JSV8Connector.cpp b/libjsconsole/JSV8Connector.cpp new file mode 100644 index 000000000..ed560a368 --- /dev/null +++ b/libjsconsole/JSV8Connector.cpp @@ -0,0 +1,54 @@ +/* + 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 . +*/ +/** @file JSV8Connector.cpp + * @author Marek Kotewicz + * @date 2015 + * Ethereum client. + */ + +#include "JSV8Connector.h" + +using namespace std; +using namespace dev; +using namespace dev::eth; + +bool JSV8Connector::StartListening() +{ + return true; +} + +bool JSV8Connector::StopListening() +{ + return true; +} + +bool JSV8Connector::SendResponse(std::string const& _response, void* _addInfo) +{ + (void)_addInfo; + m_lastResponse = _response.c_str(); + return true; +} + +void JSV8Connector::onSend(char const* payload) +{ + OnRequest(payload, NULL); +} + +JSV8Connector::~JSV8Connector() +{ + StopListening(); +} diff --git a/libjsconsole/JSV8Connector.h b/libjsconsole/JSV8Connector.h new file mode 100644 index 000000000..98cef4c2c --- /dev/null +++ b/libjsconsole/JSV8Connector.h @@ -0,0 +1,50 @@ +/* + 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 . +*/ +/** @file JSV8Connector.h + * @author Marek Kotewicz + * @date 2015 + * Ethereum client. + */ + +#pragma once + +#include +#include + +namespace dev +{ +namespace eth +{ + +class JSV8Connector: public jsonrpc::AbstractServerConnector, public JSV8RPC +{ + +public: + JSV8Connector(JSV8Engine const& _engine): JSV8RPC(_engine) {} + virtual ~JSV8Connector(); + + // implement AbstractServerConnector interface + bool StartListening(); + bool StopListening(); + bool SendResponse(std::string const& _response, void* _addInfo = nullptr); + + // implement JSV8RPC interface + void onSend(char const* payload); +}; + +} +} diff --git a/libjsengine/CMakeLists.txt b/libjsengine/CMakeLists.txt new file mode 100644 index 000000000..0023494c6 --- /dev/null +++ b/libjsengine/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_policy(SET CMP0015 NEW) +# this policy was introduced in cmake 3.0 +# remove if, once 3.0 will be used on unix +if (${CMAKE_MAJOR_VERSION} GREATER 2) + # old policy do not use MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) +endif() + +set(CMAKE_AUTOMOC OFF) + +aux_source_directory(. SRC_LIST) + +include_directories(BEFORE ${V8_INCLUDE_DIRS}) +include_directories(BEFORE ..) + +set(EXECUTABLE jsengine) + +file(GLOB HEADERS "*.h") + +include(EthUtils) +eth_add_resources("${CMAKE_CURRENT_SOURCE_DIR}/JSResources.cmake" "JSRES") +message(STATUS "HERE!!! ${JSRES}") +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS} ${JSRES}) + +# macos brew version of v8 needs to be compiled with libstdc++ +# it also needs to be dynamic library +# xcode needs libstdc++ to be explicitly set as it's attribute +if (APPLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") + set_property(TARGET ${EXECUTABLE} PROPERTY XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libstdc++") +endif() + +target_link_libraries(${EXECUTABLE} ${V8_LIBRARIES}) + +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libjsengine/Common.js b/libjsengine/Common.js new file mode 100644 index 000000000..3911409a7 --- /dev/null +++ b/libjsengine/Common.js @@ -0,0 +1,11 @@ +console = {}; +console.log = function () { +}; +console.warn = function () { +}; +console.error = function () { +}; + +setTimeout = function () { +}; + diff --git a/libjsengine/JSEngine.cpp b/libjsengine/JSEngine.cpp new file mode 100644 index 000000000..b2bad4859 --- /dev/null +++ b/libjsengine/JSEngine.cpp @@ -0,0 +1,36 @@ +/* + 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 . +*/ +/** @file JSEngine.cpp + * @author Marek Kotewicz + * @date 2015 + * Ethereum client. + */ + +#include +#include +#include "JSEngine.h" + +using namespace dev; +using namespace dev::eth; + +JSString::JSString(char const* _cstr): m_cstr(strdup(_cstr)) {} + +JSString::~JSString() +{ + if (m_cstr) + free(m_cstr); +} diff --git a/libjsengine/JSEngine.h b/libjsengine/JSEngine.h new file mode 100644 index 000000000..ce54379a1 --- /dev/null +++ b/libjsengine/JSEngine.h @@ -0,0 +1,60 @@ +/* + 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 . +*/ +/** @file JSEngine.h + * @author Marek Kotewicz + * @date 2015 + * Ethereum client. + */ + +#pragma once +#include + +namespace dev +{ +namespace eth +{ + +class JSException: public std::exception {}; +class JSPrintException: public JSException { char const* what() const noexcept { return "Cannot print expression!"; } }; + +class JSString +{ +public: + JSString(char const* _cstr); + ~JSString(); + char const* cstr() const { return m_cstr; } + +private: + char* m_cstr; +}; + +class JSValue +{ +public: + virtual JSString toString() const = 0; +}; + +template +class JSEngine +{ +public: + // should be used to evalute javascript expression + virtual T eval(char const* _cstr) const = 0; +}; + +} +} diff --git a/libjsengine/JSPrinter.cpp b/libjsengine/JSPrinter.cpp new file mode 100644 index 000000000..35e315a78 --- /dev/null +++ b/libjsengine/JSPrinter.cpp @@ -0,0 +1,23 @@ +/* + 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 . +*/ +/** @file JSPrinter.cpp + * @author Marek Kotewicz + * @date 2015 + * Ethereum client. + */ + +#include "JSPrinter.h" diff --git a/libjsengine/JSPrinter.h b/libjsengine/JSPrinter.h new file mode 100644 index 000000000..bf13fcea7 --- /dev/null +++ b/libjsengine/JSPrinter.h @@ -0,0 +1,41 @@ +/* + 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 . +*/ +/** @file JSPrinter.h + * @author Marek Kotewicz + * @date 2015 + * Ethereum client. + */ + +#pragma once + +#include "JSEngine.h" + +namespace dev +{ +namespace eth +{ + +template +class JSPrinter +{ +public: + virtual JSString print(T const& _value) const { return _value.toString(); } + virtual JSString prettyPrint(T const& _value) const { return print(_value); } +}; + +} +} diff --git a/libjsengine/JSResources.cmake b/libjsengine/JSResources.cmake new file mode 100644 index 000000000..d4370a8da --- /dev/null +++ b/libjsengine/JSResources.cmake @@ -0,0 +1,8 @@ + +set(web3 "${CMAKE_CURRENT_LIST_DIR}/../libjsqrc/ethereumjs/dist/web3.js") +set(pretty_print "${CMAKE_CURRENT_LIST_DIR}/PrettyPrint.js") +set(common "${CMAKE_CURRENT_LIST_DIR}/Common.js") + +set(ETH_RESOURCE_NAME "JSEngineResources") +set(ETH_RESOURCE_LOCATION "${CMAKE_CURRENT_BINARY_DIR}") +set(ETH_RESOURCES "web3" "pretty_print" "common") diff --git a/libjsengine/JSV8Engine.cpp b/libjsengine/JSV8Engine.cpp new file mode 100644 index 000000000..4e06f0f65 --- /dev/null +++ b/libjsengine/JSV8Engine.cpp @@ -0,0 +1,187 @@ +/* + 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 . +*/ +/** @file JSV8Engine.cpp + * @author Marek Kotewicz + * @date 2015 + * Ethereum client. + */ + +#include +#include "JSV8Engine.h" +#include "libjsengine/JSEngineResources.hpp" + +using namespace std; +using namespace dev; +using namespace dev::eth; + +namespace dev +{ +namespace eth +{ + +static char const* toCString(v8::String::Utf8Value const& _value) +{ + if (*_value) + return *_value; + throw JSPrintException(); +} + +// from: https://github.com/v8/v8-git-mirror/blob/master/samples/shell.cc +// v3.15 from: https://chromium.googlesource.com/v8/v8.git/+/3.14.5.9/samples/shell.cc +void reportException(v8::TryCatch* _tryCatch) +{ + v8::HandleScope handle_scope; + v8::String::Utf8Value exception(_tryCatch->Exception()); + char const* exceptionString = toCString(exception); + v8::Handle message = _tryCatch->Message(); + + // V8 didn't provide any extra information about this error; just + // print the exception. + if (message.IsEmpty()) + printf("%s\n", exceptionString); + else + { + // Print (filename):(line number): (message). + v8::String::Utf8Value filename(message->GetScriptResourceName()); + char const* filenameString = toCString(filename); + int linenum = message->GetLineNumber(); + printf("%s:%i: %s\n", filenameString, linenum, exceptionString); + + // Print line of source code. + v8::String::Utf8Value sourceline(message->GetSourceLine()); + char const* sourcelineString = toCString(sourceline); + printf("%s\n", sourcelineString); + + // Print wavy underline (GetUnderline is deprecated). + int start = message->GetStartColumn(); + for (int i = 0; i < start; i++) + printf(" "); + + int end = message->GetEndColumn(); + + for (int i = start; i < end; i++) + printf("^"); + + printf("\n"); + + v8::String::Utf8Value stackTrace(_tryCatch->StackTrace()); + if (stackTrace.length() > 0) + { + char const* stackTraceString = toCString(stackTrace); + printf("%s\n", stackTraceString); + } + } +} + +class JSV8Env +{ +public: + ~JSV8Env() + { + v8::V8::Dispose(); + } +}; + +class JSV8Scope +{ +public: + JSV8Scope(): + m_handleScope(), + m_context(v8::Context::New(NULL, v8::ObjectTemplate::New())), + m_contextScope(m_context) + { + m_context->Enter(); + } + + ~JSV8Scope() + { + m_context->Exit(); + m_context.Dispose(); + } + + v8::Persistent const& context() const { return m_context; } + +private: + v8::HandleScope m_handleScope; + v8::Persistent m_context; + v8::Context::Scope m_contextScope; +}; + +} +} + +JSV8Env JSV8Engine::s_env = JSV8Env(); + +JSString JSV8Value::toString() const +{ + if (m_value.IsEmpty()) + return ""; + + else if (m_value->IsUndefined()) + return "undefined"; + + v8::String::Utf8Value str(m_value); + return toCString(str); +} + +JSV8Engine::JSV8Engine(): m_scope(new JSV8Scope()) +{ + JSEngineResources resources; + string common = resources.loadResourceAsString("common"); + string web3 = resources.loadResourceAsString("web3"); + eval(common.c_str()); + eval(web3.c_str()); + eval("web3 = require('web3');"); +} + +JSV8Engine::~JSV8Engine() +{ + delete m_scope; +} + +JSV8Value JSV8Engine::eval(char const* _cstr) const +{ + v8::HandleScope handleScope; + v8::TryCatch tryCatch; + v8::Local source = v8::String::New(_cstr); + v8::Local name(v8::String::New("(shell)")); + v8::ScriptOrigin origin(name); + v8::Handle script = v8::Script::Compile(source, &origin); + + // Make sure to wrap the exception in a new handle because + // the handle returned from the TryCatch is destroyed + if (script.IsEmpty()) + { + reportException(&tryCatch); + return v8::Exception::Error(v8::Local::New(tryCatch.Message()->Get())); + } + + auto result = script->Run(); + + if (result.IsEmpty()) + { + reportException(&tryCatch); + return v8::Exception::Error(v8::Local::New(tryCatch.Message()->Get())); + } + + return result; +} + +v8::Handle const& JSV8Engine::context() const +{ + return m_scope->context(); +} diff --git a/libjsengine/JSV8Engine.h b/libjsengine/JSV8Engine.h new file mode 100644 index 000000000..56459c5d0 --- /dev/null +++ b/libjsengine/JSV8Engine.h @@ -0,0 +1,61 @@ +/* + 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 . +*/ +/** @file JSV8Engine.h + * @author Marek Kotewicz + * @date 2015 + * Ethereum client. + */ + +#pragma once + +#include +#include "JSEngine.h" + +namespace dev +{ +namespace eth +{ + +class JSV8Env; +class JSV8Scope; + +class JSV8Value: public JSValue +{ +public: + JSV8Value(v8::Handle _value): m_value(_value) {} + JSString toString() const; + v8::Handle const& value() const { return m_value; } + +private: + v8::Handle m_value; +}; + +class JSV8Engine: public JSEngine +{ +public: + JSV8Engine(); + virtual ~JSV8Engine(); + JSV8Value eval(char const* _cstr) const; + v8::Handle const& context() const; + +private: + static JSV8Env s_env; + JSV8Scope* m_scope; +}; + +} +} diff --git a/libjsengine/JSV8Printer.cpp b/libjsengine/JSV8Printer.cpp new file mode 100644 index 000000000..93c235859 --- /dev/null +++ b/libjsengine/JSV8Printer.cpp @@ -0,0 +1,49 @@ +/* + 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 . +*/ +/** @file JSV8Printer.cpp + * @author Marek Kotewicz + * @date 2015 + * Ethereum client. + */ + +#include +#include "JSV8Printer.h" +#include "libjsengine/JSEngineResources.hpp" + +using namespace std; +using namespace dev; +using namespace eth; + +JSV8Printer::JSV8Printer(JSV8Engine const& _engine): m_engine(_engine) +{ + JSEngineResources resources; + string prettyPrint = resources.loadResourceAsString("pretty_print"); + m_engine.eval(prettyPrint.c_str()); +} + +JSString JSV8Printer::prettyPrint(JSV8Value const& _value) const +{ + v8::HandleScope handleScope; + v8::Local pp = v8::String::New("prettyPrint"); + v8::Handle func = v8::Handle::Cast(m_engine.context()->Global()->Get(pp)); + v8::Local values[1] = {v8::Local::New(_value.value())}; + v8::Local res = func->Call(func, 1, values); + v8::String::Utf8Value str(res); + if (*str) + return *str; + throw JSPrintException(); +} diff --git a/libjsengine/JSV8Printer.h b/libjsengine/JSV8Printer.h new file mode 100644 index 000000000..2ec9c78b6 --- /dev/null +++ b/libjsengine/JSV8Printer.h @@ -0,0 +1,43 @@ +/* + 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 . +*/ +/** @file JSV8Printer.h + * @author Marek Kotewicz + * @date 2015 + * Ethereum client. + */ + +#pragma once + +#include "JSPrinter.h" +#include "JSV8Engine.h" + +namespace dev +{ +namespace eth +{ + +class JSV8Printer: public JSPrinter +{ +public: + JSV8Printer(JSV8Engine const& _engine); + JSString prettyPrint(JSV8Value const& _value) const; +private: + JSV8Engine const& m_engine; +}; + +} +} diff --git a/libjsengine/JSV8RPC.cpp b/libjsengine/JSV8RPC.cpp new file mode 100644 index 000000000..994cfbbf2 --- /dev/null +++ b/libjsengine/JSV8RPC.cpp @@ -0,0 +1,84 @@ +/* + 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 . +*/ +/** @file JSV8RPC.cpp + * @author Marek Kotewicz + * @date 2015 + * Ethereum client. + */ + +#include "JSV8RPC.h" + +using namespace dev; +using namespace dev::eth; + +namespace dev +{ +namespace eth +{ + +v8::Handle JSV8RPCSend(v8::Arguments const& _args) +{ + v8::Local JSON = v8::String::New("JSON"); + v8::Local parse = v8::String::New("parse"); + v8::Local stringify = v8::String::New("stringify"); + v8::Handle jsonObject = v8::Handle::Cast(v8::Context::GetCurrent()->Global()->Get(JSON)); + v8::Handle parseFunc = v8::Handle::Cast(jsonObject->Get(parse)); + v8::Handle stringifyFunc = v8::Handle::Cast(jsonObject->Get(stringify)); + + v8::Local self = _args.Holder(); + v8::Local wrap = v8::Local::Cast(self->GetInternalField(0)); + JSV8RPC* that = static_cast(wrap->Value()); + v8::Local vals[1] = {_args[0]->ToObject()}; + v8::Local stringifiedArg = stringifyFunc->Call(stringifyFunc, 1, vals); + v8::String::Utf8Value str(stringifiedArg); + that->onSend(*str); + + v8::Local values[1] = {v8::String::New(that->lastResponse())}; + return parseFunc->Call(parseFunc, 1, values); +} + +} +} + +JSV8RPC::JSV8RPC(JSV8Engine const& _engine): m_engine(_engine) +{ + v8::HandleScope scope; + v8::Local rpcTemplate = v8::ObjectTemplate::New(); + rpcTemplate->SetInternalFieldCount(1); + rpcTemplate->Set(v8::String::New("send"), + v8::FunctionTemplate::New(JSV8RPCSend)); + rpcTemplate->Set(v8::String::New("sendAsync"), + v8::FunctionTemplate::New(JSV8RPCSend)); + + v8::Local obj = rpcTemplate->NewInstance(); + obj->SetInternalField(0, v8::External::New(this)); + + v8::Local web3 = v8::String::New("web3"); + v8::Local setProvider = v8::String::New("setProvider"); + v8::Handle web3object = v8::Handle::Cast(m_engine.context()->Global()->Get(web3)); + v8::Handle func = v8::Handle::Cast(web3object->Get(setProvider)); + v8::Local values[1] = {obj}; + func->Call(func, 1, values); + + m_lastResponse = R"( + { + "id": 1, + "jsonrpc": "2.0", + "error": "Uninitalized JSV8RPC!" + } + )"; +} diff --git a/libjsengine/JSV8RPC.h b/libjsengine/JSV8RPC.h new file mode 100644 index 000000000..a2180ef51 --- /dev/null +++ b/libjsengine/JSV8RPC.h @@ -0,0 +1,47 @@ +/* + 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 . +*/ +/** @file JSV8RPC.h + * @author Marek Kotewicz + * @date 2015 + * Ethereum client. + */ + +#pragma once + +#include + +namespace dev +{ +namespace eth +{ + +class JSV8RPC +{ +public: + JSV8RPC(JSV8Engine const& _engine); + virtual void onSend(char const* _payload) = 0; + char const* lastResponse() const { return m_lastResponse; } + +private: + JSV8Engine const& m_engine; + +protected: + char const* m_lastResponse; +}; + +} +} diff --git a/libjsengine/PrettyPrint.js b/libjsengine/PrettyPrint.js new file mode 100644 index 000000000..f617cf29c --- /dev/null +++ b/libjsengine/PrettyPrint.js @@ -0,0 +1,91 @@ +var prettyPrint = (function () { + function pp(object, indent) { + try { + JSON.stringify(object) + } catch(e) { + return pp(e, indent); + } + var str = ""; + if(object instanceof Array) { + str += "["; + for(var i = 0, l = object.length; i < l; i++) { + str += pp(object[i], indent); + if(i < l-1) { + str += ", "; + } + } + str += " ]"; + } else if (object instanceof Error) { + str += "\033[31m" + "Error:\033[0m " + object.message; + } else if (object === null) { + str += "\033[1m\033[30m" + "null"; + } else if(typeof(object) === "undefined") { + str += "\033[1m\033[30m" + object; + } else if (isBigNumber(object)) { + str += "\033[32m'" + object.toString(10) + "'"; + } else if(typeof(object) === "object") { + str += "{\n"; + indent += " "; + var last = getFields(object).pop() + getFields(object).forEach(function (k) { + str += indent + k + ": "; + try { + str += pp(object[k], indent); + } catch (e) { + str += pp(e, indent); + } + if(k !== last) { + str += ","; + } + str += "\n"; + }); + str += indent.substr(2, indent.length) + "}"; + } else if(typeof(object) === "string") { + str += "\033[32m'" + object + "'"; + } else if(typeof(object) === "number") { + str += "\033[31m" + object; + } else if(typeof(object) === "function") { + str += "\033[35m[Function]"; + } else { + str += object; + } + str += "\033[0m"; + return str; + } + var redundantFields = [ + 'valueOf', + 'toString', + 'toLocaleString', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'constructor', + '__defineGetter__', + '__defineSetter__', + '__lookupGetter__', + '__lookupSetter__', + '__proto__' + ]; + var getFields = function (object) { + var result = Object.getOwnPropertyNames(object); + if (object.constructor && object.constructor.prototype) { + result = result.concat(Object.getOwnPropertyNames(object.constructor.prototype)); + } + return result.filter(function (field) { + return redundantFields.indexOf(field) === -1; + }); + }; + var isBigNumber = function (object) { + return (!!object.constructor && object.constructor.name === 'BigNumber') || + (typeof BigNumber !== 'undefined' && object instanceof BigNumber) + }; + function prettyPrintInner(/* */) { + var args = arguments; + var ret = ""; + for(var i = 0, l = args.length; i < l; i++) { + ret += pp(args[i], "") + "\n"; + } + return ret; + }; + return prettyPrintInner; +})(); diff --git a/libjsqrc/ethereumjs/bower.json b/libjsqrc/ethereumjs/bower.json index f8abf431d..db9a4702d 100644 --- a/libjsqrc/ethereumjs/bower.json +++ b/libjsqrc/ethereumjs/bower.json @@ -1,7 +1,7 @@ { "name": "web3", "namespace": "ethereum", - "version": "0.3.3", + "version": "0.3.6", "description": "Ethereum Compatible JavaScript API", "main": [ "./dist/web3.js", diff --git a/libjsqrc/ethereumjs/dist/web3-light.js b/libjsqrc/ethereumjs/dist/web3-light.js index bfc246f66..c128634de 100644 --- a/libjsqrc/ethereumjs/dist/web3-light.js +++ b/libjsqrc/ethereumjs/dist/web3-light.js @@ -22,118 +22,29 @@ require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof requ * @date 2014 */ -var utils = require('../utils/utils'); var coder = require('./coder'); -var solUtils = require('./utils'); - -/** - * Formats input params to bytes - * - * @method formatInput - * @param {Array} abi inputs of method - * @param {Array} params that will be formatted to bytes - * @returns bytes representation of input params - */ -var formatInput = function (inputs, params) { - var i = inputs.map(function (input) { - return input.type; - }); - return coder.encodeParams(i, params); -}; - -/** - * Formats output bytes back to param list - * - * @method formatOutput - * @param {Array} abi outputs of method - * @param {String} bytes represention of output - * @returns {Array} output params - */ -var formatOutput = function (outs, bytes) { - var o = outs.map(function (out) { - return out.type; - }); - - return coder.decodeParams(o, bytes); -}; - -/** - * Should be called to create input parser for contract with given abi - * - * @method inputParser - * @param {Array} contract abi - * @returns {Object} input parser object for given json abi - * TODO: refactor creating the parser, do not double logic from contract - */ -var inputParser = function (json) { - var parser = {}; - json.forEach(function (method) { - var displayName = utils.extractDisplayName(method.name); - var typeName = utils.extractTypeName(method.name); - - var impl = function () { - var params = Array.prototype.slice.call(arguments); - return formatInput(method.inputs, params); - }; - - if (parser[displayName] === undefined) { - parser[displayName] = impl; - } - - parser[displayName][typeName] = impl; - }); - - return parser; -}; - -/** - * Should be called to create output parser for contract with given abi - * - * @method outputParser - * @param {Array} contract abi - * @returns {Object} output parser for given json abi - */ -var outputParser = function (json) { - var parser = {}; - json.forEach(function (method) { - - var displayName = utils.extractDisplayName(method.name); - var typeName = utils.extractTypeName(method.name); - - var impl = function (output) { - return formatOutput(method.outputs, output); - }; - - if (parser[displayName] === undefined) { - parser[displayName] = impl; - } - - parser[displayName][typeName] = impl; - }); - - return parser; -}; +var utils = require('./utils'); var formatConstructorParams = function (abi, params) { - var constructor = solUtils.getConstructor(abi, params.length); + var constructor = utils.getConstructor(abi, params.length); if (!constructor) { if (params.length > 0) { console.warn("didn't found matching constructor, using default one"); } return ''; } - return formatInput(constructor.inputs, params); + + return coder.encodeParams(constructor.inputs.map(function (input) { + return input.type; + }), params); }; module.exports = { - inputParser: inputParser, - outputParser: outputParser, - formatInput: formatInput, - formatOutput: formatOutput, formatConstructorParams: formatConstructorParams }; -},{"../utils/utils":8,"./coder":2,"./utils":5}],2:[function(require,module,exports){ + +},{"./coder":2,"./utils":5}],2:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -213,9 +124,8 @@ SolidityType.prototype.formatInput = function (param, arrayType) { return param.map(function (p) { return self._inputFormatter(p); }).reduce(function (acc, current) { - acc.appendArrayElement(current); - return acc; - }, new SolidityParam('', f.formatInputInt(param.length).value)); + return acc.combine(current); + }, f.formatInputInt(param.length)).withOffset(32); } return this._inputFormatter(param); }; @@ -232,9 +142,9 @@ SolidityType.prototype.formatOutput = function (param, arrayType) { if (arrayType) { // let's assume, that we solidity will never return long arrays :P var result = []; - var length = new BigNumber(param.prefix, 16); + var length = new BigNumber(param.dynamicPart().slice(0, 64), 16); for (var i = 0; i < length * 64; i += 64) { - result.push(this._outputFormatter(new SolidityParam(param.suffix.slice(i, i + 64)))); + result.push(this._outputFormatter(new SolidityParam(param.dynamicPart().substr(i + 64, 64)))); } return result; } @@ -242,31 +152,21 @@ SolidityType.prototype.formatOutput = function (param, arrayType) { }; /** - * Should be used to check if a type is variadic + * Should be used to slice single param from bytes * - * @method isVariadicType - * @param {String} type - * @returns {Bool} true if the type is variadic - */ -SolidityType.prototype.isVariadicType = function (type) { - return isArrayType(type) || this._mode === 'bytes'; -}; - -/** - * Should be used to shift param from params group - * - * @method shiftParam + * @method sliceParam + * @param {String} bytes + * @param {Number} index of param to slice * @param {String} type - * @returns {SolidityParam} shifted param + * @returns {SolidityParam} param */ -SolidityType.prototype.shiftParam = function (type, param) { +SolidityType.prototype.sliceParam = function (bytes, index, type) { if (this._mode === 'bytes') { - return param.shiftBytes(); + return SolidityParam.decodeBytes(bytes, index); } else if (isArrayType(type)) { - var length = new BigNumber(param.prefix.slice(0, 64), 16); - return param.shiftArray(length); + return SolidityParam.decodeArray(bytes, index); } - return param.shiftValue(); + return SolidityParam.decodeParam(bytes, index); }; /** @@ -296,28 +196,6 @@ SolidityCoder.prototype._requireType = function (type) { return solidityType; }; -/** - * Should be used to transform plain bytes to SolidityParam object - * - * @method _bytesToParam - * @param {Array} types of params - * @param {String} bytes to be transformed to SolidityParam - * @return {SolidityParam} SolidityParam for this group of params - */ -SolidityCoder.prototype._bytesToParam = function (types, bytes) { - var self = this; - var prefixTypes = types.reduce(function (acc, type) { - return self._requireType(type).isVariadicType(type) ? acc + 1 : acc; - }, 0); - var valueTypes = types.length - prefixTypes; - - var prefix = bytes.slice(0, prefixTypes * 64); - bytes = bytes.slice(prefixTypes * 64); - var value = bytes.slice(0, valueTypes * 64); - var suffix = bytes.slice(valueTypes * 64); - return new SolidityParam(value, prefix, suffix); -}; - /** * Should be used to transform plain param of given type to SolidityParam * @@ -352,24 +230,11 @@ SolidityCoder.prototype.encodeParam = function (type, param) { */ SolidityCoder.prototype.encodeParams = function (types, params) { var self = this; - return types.map(function (type, index) { + var solidityParams = types.map(function (type, index) { return self._formatInput(type, params[index]); - }).reduce(function (acc, solidityParam) { - acc.append(solidityParam); - return acc; - }, new SolidityParam()).encode(); -}; + }); -/** - * Should be used to transform SolidityParam to plain param - * - * @method _formatOutput - * @param {String} type - * @param {SolidityParam} param - * @return {Object} plain param - */ -SolidityCoder.prototype._formatOutput = function (type, param) { - return this._requireType(type).formatOutput(param, isArrayType(type)); + return SolidityParam.encodeList(solidityParams); }; /** @@ -381,7 +246,7 @@ SolidityCoder.prototype._formatOutput = function (type, param) { * @return {Object} plain param */ SolidityCoder.prototype.decodeParam = function (type, bytes) { - return this._formatOutput(type, this._bytesToParam([type], bytes)); + return this.decodeParams([type], bytes)[0]; }; /** @@ -394,10 +259,9 @@ SolidityCoder.prototype.decodeParam = function (type, bytes) { */ SolidityCoder.prototype.decodeParams = function (types, bytes) { var self = this; - var param = this._bytesToParam(types, bytes); - return types.map(function (type) { + return types.map(function (type, index) { var solidityType = self._requireType(type); - var p = solidityType.shiftParam(type, param); + var p = solidityType.sliceParam(bytes, index, type); return solidityType.formatOutput(p, isArrayType(type)); }); }; @@ -530,7 +394,7 @@ var formatInputBytes = function (value) { */ var formatInputDynamicBytes = function (value) { var result = utils.fromAscii(value, c.ETH_PADDING).substr(2); - return new SolidityParam('', formatInputInt(value.length).value, result); + return new SolidityParam(formatInputInt(value.length).value + result, 32); }; /** @@ -576,7 +440,7 @@ var signedIsNegative = function (value) { * @returns {BigNumber} right-aligned output bytes formatted to big number */ var formatOutputInt = function (param) { - var value = param.value || "0"; + var value = param.staticPart() || "0"; // check if it's negative number // it it is, return two's complement @@ -594,7 +458,7 @@ var formatOutputInt = function (param) { * @returns {BigNumeber} right-aligned output bytes formatted to uint */ var formatOutputUInt = function (param) { - var value = param.value || "0"; + var value = param.staticPart() || "0"; return new BigNumber(value, 16); }; @@ -628,7 +492,7 @@ var formatOutputUReal = function (param) { * @returns {Boolean} right-aligned input bytes formatted to bool */ var formatOutputBool = function (param) { - return param.value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false; + return param.staticPart() === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false; }; /** @@ -640,7 +504,7 @@ var formatOutputBool = function (param) { */ var formatOutputBytes = function (param) { // length might also be important! - return utils.toAscii(param.value); + return utils.toAscii(param.staticPart()); }; /** @@ -652,7 +516,7 @@ var formatOutputBytes = function (param) { */ var formatOutputDynamicBytes = function (param) { // length might also be important! - return utils.toAscii(param.suffix); + return utils.toAscii(param.dynamicPart().slice(64)); }; /** @@ -663,7 +527,7 @@ var formatOutputDynamicBytes = function (param) { * @returns {String} address */ var formatOutputAddress = function (param) { - var value = param.value; + var value = param.staticPart(); return "0x" + value.slice(value.length - 40, value.length); }; @@ -707,91 +571,196 @@ module.exports = { * @date 2015 */ +var utils = require('../utils/utils'); + /** * SolidityParam object prototype. * Should be used when encoding, decoding solidity bytes */ -var SolidityParam = function (value, prefix, suffix) { - this.prefix = prefix || ''; +var SolidityParam = function (value, offset) { this.value = value || ''; - this.suffix = suffix || ''; + this.offset = offset; // offset in bytes +}; + +/** + * This method should be used to get length of params's dynamic part + * + * @method dynamicPartLength + * @returns {Number} length of dynamic part (in bytes) + */ +SolidityParam.prototype.dynamicPartLength = function () { + return this.dynamicPart().length / 2; +}; + +/** + * This method should be used to create copy of solidity param with different offset + * + * @method withOffset + * @param {Number} offset length in bytes + * @returns {SolidityParam} new solidity param with applied offset + */ +SolidityParam.prototype.withOffset = function (offset) { + return new SolidityParam(this.value, offset); }; /** - * This method should be used to encode two params one after another + * This method should be used to combine solidity params together + * eg. when appending an array * - * @method append - * @param {SolidityParam} param that it appended after this + * @method combine + * @param {SolidityParam} param with which we should combine + * @param {SolidityParam} result of combination */ -SolidityParam.prototype.append = function (param) { - this.prefix += param.prefix; - this.value += param.value; - this.suffix += param.suffix; +SolidityParam.prototype.combine = function (param) { + return new SolidityParam(this.value + param.value); }; /** - * This method should be used to encode next param in an array + * This method should be called to check if param has dynamic size. + * If it has, it returns true, otherwise false * - * @method appendArrayElement - * @param {SolidityParam} param that is appended to an array + * @method isDynamic + * @returns {Boolean} */ -SolidityParam.prototype.appendArrayElement = function (param) { - this.suffix += param.value; - this.prefix += param.prefix; - // TODO: suffix not supported = it's required for nested arrays; +SolidityParam.prototype.isDynamic = function () { + return this.value.length > 64; }; /** - * This method should be used to create bytearrays from param + * This method should be called to transform offset to bytes + * + * @method offsetAsBytes + * @returns {String} bytes representation of offset + */ +SolidityParam.prototype.offsetAsBytes = function () { + return !this.isDynamic() ? '' : utils.padLeft(utils.toTwosComplement(this.offset).toString(16), 64); +}; + +/** + * This method should be called to get static part of param + * + * @method staticPart + * @returns {String} offset if it is a dynamic param, otherwise value + */ +SolidityParam.prototype.staticPart = function () { + if (!this.isDynamic()) { + return this.value; + } + return this.offsetAsBytes(); +}; + +/** + * This method should be called to get dynamic part of param + * + * @method dynamicPart + * @returns {String} returns a value if it is a dynamic param, otherwise empty string + */ +SolidityParam.prototype.dynamicPart = function () { + return this.isDynamic() ? this.value : ''; +}; + +/** + * This method should be called to encode param * * @method encode - * @return {String} encoded param(s) + * @returns {String} */ SolidityParam.prototype.encode = function () { - return this.prefix + this.value + this.suffix; + return this.staticPart() + this.dynamicPart(); }; /** - * This method should be used to shift first param from group of params + * This method should be called to encode array of params * - * @method shiftValue - * @return {SolidityParam} first value param + * @method encodeList + * @param {Array[SolidityParam]} params + * @returns {String} */ -SolidityParam.prototype.shiftValue = function () { - var value = this.value.slice(0, 64); - this.value = this.value.slice(64); - return new SolidityParam(value); +SolidityParam.encodeList = function (params) { + + // updating offsets + var totalOffset = params.length * 32; + var offsetParams = params.map(function (param) { + if (!param.isDynamic()) { + return param; + } + var offset = totalOffset; + totalOffset += param.dynamicPartLength(); + return param.withOffset(offset); + }); + + // encode everything! + return offsetParams.reduce(function (result, param) { + return result + param.dynamicPart(); + }, offsetParams.reduce(function (result, param) { + return result + param.staticPart(); + }, '')); }; /** - * This method should be used to first bytes param from group of params + * This method should be used to decode plain (static) solidity param at given index * - * @method shiftBytes - * @return {SolidityParam} first bytes param + * @method decodeParam + * @param {String} bytes + * @param {Number} index + * @returns {SolidityParam} */ -SolidityParam.prototype.shiftBytes = function () { - return this.shiftArray(1); +SolidityParam.decodeParam = function (bytes, index) { + index = index || 0; + return new SolidityParam(bytes.substr(index * 64, 64)); }; /** - * This method should be used to shift an array from group of params - * - * @method shiftArray - * @param {Number} size of an array to shift - * @return {SolidityParam} first array param + * This method should be called to get offset value from bytes at given index + * + * @method getOffset + * @param {String} bytes + * @param {Number} index + * @returns {Number} offset as number + */ +var getOffset = function (bytes, index) { + // we can do this cause offset is rather small + return parseInt('0x' + bytes.substr(index * 64, 64)); +}; + +/** + * This method should be called to decode solidity bytes param at given index + * + * @method decodeBytes + * @param {String} bytes + * @param {Number} index + * @returns {SolidityParam} + */ +SolidityParam.decodeBytes = function (bytes, index) { + index = index || 0; + //TODO add support for strings longer than 32 bytes + //var length = parseInt('0x' + bytes.substr(offset * 64, 64)); + + var offset = getOffset(bytes, index); + + // 2 * , cause we also parse length + return new SolidityParam(bytes.substr(offset * 2, 2 * 64)); +}; + +/** + * This method should be used to decode solidity array at given index + * + * @method decodeArray + * @param {String} bytes + * @param {Number} index + * @returns {SolidityParam} */ -SolidityParam.prototype.shiftArray = function (length) { - var prefix = this.prefix.slice(0, 64); - this.prefix = this.value.slice(64); - var suffix = this.suffix.slice(0, 64 * length); - this.suffix = this.suffix.slice(64 * length); - return new SolidityParam('', prefix, suffix); +SolidityParam.decodeArray = function (bytes, index) { + index = index || 0; + var offset = getOffset(bytes, index); + var length = parseInt('0x' + bytes.substr(offset * 2, 64)); + return new SolidityParam(bytes.substr(offset * 2, (length + 1) * 64)); }; module.exports = SolidityParam; -},{}],5:[function(require,module,exports){ +},{"../utils/utils":8}],5:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -828,6 +797,11 @@ var getConstructor = function (abi, numberOfArgs) { })[0]; }; +//var getSupremeType = function (type) { + //return type.substr(0, type.indexOf('[')) + ']'; +//}; + + module.exports = { getConstructor: getConstructor }; @@ -1394,7 +1368,7 @@ module.exports = { },{"bignumber.js":"bignumber.js"}],9:[function(require,module,exports){ module.exports={ - "version": "0.3.3" + "version": "0.3.6" } },{}],10:[function(require,module,exports){ @@ -1796,7 +1770,7 @@ module.exports = { /** * Web3 - * + * * @module web3 */ @@ -1850,16 +1824,16 @@ var uncleCountCall = function (args) { /// @returns an array of objects describing web3.eth api methods var getBalance = new Method({ - name: 'getBalance', - call: 'eth_getBalance', + name: 'getBalance', + call: 'eth_getBalance', params: 2, inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter], outputFormatter: formatters.outputBigNumberFormatter }); var getStorageAt = new Method({ - name: 'getStorageAt', - call: 'eth_getStorageAt', + name: 'getStorageAt', + call: 'eth_getStorageAt', params: 3, inputFormatter: [null, utils.toHex, formatters.inputDefaultBlockNumberFormatter] }); @@ -1872,7 +1846,7 @@ var getCode = new Method({ }); var getBlock = new Method({ - name: 'getBlock', + name: 'getBlock', call: blockCall, params: 2, inputFormatter: [formatters.inputBlockNumberFormatter, function (val) { return !!val; }], @@ -1997,6 +1971,11 @@ var properties = [ name: 'mining', getter: 'eth_mining' }), + new Property({ + name: 'hashrate', + getter: 'eth_hashrate', + outputFormatter: utils.toDecimal + }), new Property({ name: 'gasPrice', getter: 'eth_gasPrice', @@ -2118,7 +2097,7 @@ SolidityEvent.prototype.encode = function (indexed, options) { ['fromBlock', 'toBlock'].filter(function (f) { return options[f] !== undefined; }).forEach(function (f) { - result[f] = utils.toHex(options[f]); + result[f] = formatters.inputBlockNumberFormatter(options[f]); }); result.topics = []; @@ -2447,7 +2426,7 @@ var inputTransactionFormatter = function (options){ delete options.code; } - ['gasPrice', 'gas', 'value'].filter(function (key) { + ['gasPrice', 'gas', 'value', 'nonce'].filter(function (key) { return options[key] !== undefined; }).forEach(function(key){ options[key] = utils.fromDecimal(options[key]); @@ -2796,15 +2775,32 @@ HttpProvider.prototype.send = function (payload) { //if (request.status !== 200) { //return; //} - return JSON.parse(request.responseText); + + var result = request.responseText; + + try { + result = JSON.parse(result); + } catch(e) { + throw errors.InvalidResponse(result); + } + + return result; }; HttpProvider.prototype.sendAsync = function (payload, callback) { var request = new XMLHttpRequest(); request.onreadystatechange = function() { if (request.readyState === 4) { - // TODO: handle the error properly here!!! - callback(null, JSON.parse(request.responseText)); + var result = request.responseText; + var error = null; + + try { + result = JSON.parse(result); + } catch(e) { + error = errors.InvalidResponse(result); + } + + callback(error, result); } }; diff --git a/libjsqrc/ethereumjs/dist/web3-light.js.map b/libjsqrc/ethereumjs/dist/web3-light.js.map index 41c3fe4e1..31e9b5a44 100644 --- a/libjsqrc/ethereumjs/dist/web3-light.js.map +++ b/libjsqrc/ethereumjs/dist/web3-light.js.map @@ -34,30 +34,30 @@ "index.js" ], "names": [], - "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1dA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrGA;;ACAA;AACA;AACA;AACA;AACA;;ACJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", + "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1dA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5PA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrGA;;ACAA;AACA;AACA;AACA;AACA;;ACJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", "file": "generated.js", "sourceRoot": "", "sourcesContent": [ "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o.\n*/\n/** \n * @file abi.js\n * @author Marek Kotewicz \n * @author Gav Wood \n * @date 2014\n */\n\nvar utils = require('../utils/utils');\nvar coder = require('./coder');\nvar solUtils = require('./utils');\n\n/**\n * Formats input params to bytes\n *\n * @method formatInput\n * @param {Array} abi inputs of method\n * @param {Array} params that will be formatted to bytes\n * @returns bytes representation of input params\n */\nvar formatInput = function (inputs, params) {\n var i = inputs.map(function (input) {\n return input.type;\n });\n return coder.encodeParams(i, params);\n};\n\n/** \n * Formats output bytes back to param list\n *\n * @method formatOutput\n * @param {Array} abi outputs of method\n * @param {String} bytes represention of output\n * @returns {Array} output params\n */\nvar formatOutput = function (outs, bytes) {\n var o = outs.map(function (out) {\n return out.type;\n });\n \n return coder.decodeParams(o, bytes); \n};\n\n/**\n * Should be called to create input parser for contract with given abi\n *\n * @method inputParser\n * @param {Array} contract abi\n * @returns {Object} input parser object for given json abi\n * TODO: refactor creating the parser, do not double logic from contract\n */\nvar inputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n var displayName = utils.extractDisplayName(method.name);\n var typeName = utils.extractTypeName(method.name);\n\n var impl = function () {\n var params = Array.prototype.slice.call(arguments);\n return formatInput(method.inputs, params);\n };\n\n if (parser[displayName] === undefined) {\n parser[displayName] = impl;\n }\n\n parser[displayName][typeName] = impl;\n });\n\n return parser;\n};\n\n/**\n * Should be called to create output parser for contract with given abi\n *\n * @method outputParser\n * @param {Array} contract abi\n * @returns {Object} output parser for given json abi\n */\nvar outputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n\n var displayName = utils.extractDisplayName(method.name);\n var typeName = utils.extractTypeName(method.name);\n\n var impl = function (output) {\n return formatOutput(method.outputs, output);\n };\n\n if (parser[displayName] === undefined) {\n parser[displayName] = impl;\n }\n\n parser[displayName][typeName] = impl;\n });\n\n return parser;\n};\n\nvar formatConstructorParams = function (abi, params) {\n var constructor = solUtils.getConstructor(abi, params.length);\n if (!constructor) {\n if (params.length > 0) {\n console.warn(\"didn't found matching constructor, using default one\");\n }\n return '';\n }\n return formatInput(constructor.inputs, params);\n};\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n formatInput: formatInput,\n formatOutput: formatOutput,\n formatConstructorParams: formatConstructorParams\n};\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file coder.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar BigNumber = require('bignumber.js');\nvar utils = require('../utils/utils');\nvar f = require('./formatters');\nvar SolidityParam = require('./param');\n\n/**\n * Should be used to check if a type is an array type\n *\n * @method isArrayType\n * @param {String} type\n * @return {Bool} true is the type is an array, otherwise false\n */\nvar isArrayType = function (type) {\n return type.slice(-2) === '[]';\n};\n\n/**\n * SolidityType prototype is used to encode/decode solidity params of certain type\n */\nvar SolidityType = function (config) {\n this._name = config.name;\n this._match = config.match;\n this._mode = config.mode;\n this._inputFormatter = config.inputFormatter;\n this._outputFormatter = config.outputFormatter;\n};\n\n/**\n * Should be used to determine if this SolidityType do match given type\n *\n * @method isType\n * @param {String} name\n * @return {Bool} true if type match this SolidityType, otherwise false\n */\nSolidityType.prototype.isType = function (name) {\n if (this._match === 'strict') {\n return this._name === name || (name.indexOf(this._name) === 0 && name.slice(this._name.length) === '[]');\n } else if (this._match === 'prefix') {\n // TODO better type detection!\n return name.indexOf(this._name) === 0;\n }\n};\n\n/**\n * Should be used to transform plain param to SolidityParam object\n *\n * @method formatInput\n * @param {Object} param - plain object, or an array of objects\n * @param {Bool} arrayType - true if a param should be encoded as an array\n * @return {SolidityParam} encoded param wrapped in SolidityParam object \n */\nSolidityType.prototype.formatInput = function (param, arrayType) {\n if (utils.isArray(param) && arrayType) { // TODO: should fail if this two are not the same\n var self = this;\n return param.map(function (p) {\n return self._inputFormatter(p);\n }).reduce(function (acc, current) {\n acc.appendArrayElement(current);\n return acc;\n }, new SolidityParam('', f.formatInputInt(param.length).value));\n } \n return this._inputFormatter(param);\n};\n\n/**\n * Should be used to transoform SolidityParam to plain param\n *\n * @method formatOutput\n * @param {SolidityParam} byteArray\n * @param {Bool} arrayType - true if a param should be decoded as an array\n * @return {Object} plain decoded param\n */\nSolidityType.prototype.formatOutput = function (param, arrayType) {\n if (arrayType) {\n // let's assume, that we solidity will never return long arrays :P \n var result = [];\n var length = new BigNumber(param.prefix, 16);\n for (var i = 0; i < length * 64; i += 64) {\n result.push(this._outputFormatter(new SolidityParam(param.suffix.slice(i, i + 64))));\n }\n return result;\n }\n return this._outputFormatter(param);\n};\n\n/**\n * Should be used to check if a type is variadic\n *\n * @method isVariadicType\n * @param {String} type\n * @returns {Bool} true if the type is variadic\n */\nSolidityType.prototype.isVariadicType = function (type) {\n return isArrayType(type) || this._mode === 'bytes';\n};\n\n/**\n * Should be used to shift param from params group\n *\n * @method shiftParam\n * @param {String} type\n * @returns {SolidityParam} shifted param\n */\nSolidityType.prototype.shiftParam = function (type, param) {\n if (this._mode === 'bytes') {\n return param.shiftBytes();\n } else if (isArrayType(type)) {\n var length = new BigNumber(param.prefix.slice(0, 64), 16);\n return param.shiftArray(length);\n }\n return param.shiftValue();\n};\n\n/**\n * SolidityCoder prototype should be used to encode/decode solidity params of any type\n */\nvar SolidityCoder = function (types) {\n this._types = types;\n};\n\n/**\n * This method should be used to transform type to SolidityType\n *\n * @method _requireType\n * @param {String} type\n * @returns {SolidityType} \n * @throws {Error} throws if no matching type is found\n */\nSolidityCoder.prototype._requireType = function (type) {\n var solidityType = this._types.filter(function (t) {\n return t.isType(type);\n })[0];\n\n if (!solidityType) {\n throw Error('invalid solidity type!: ' + type);\n }\n\n return solidityType;\n};\n\n/**\n * Should be used to transform plain bytes to SolidityParam object\n *\n * @method _bytesToParam\n * @param {Array} types of params\n * @param {String} bytes to be transformed to SolidityParam\n * @return {SolidityParam} SolidityParam for this group of params\n */\nSolidityCoder.prototype._bytesToParam = function (types, bytes) {\n var self = this;\n var prefixTypes = types.reduce(function (acc, type) {\n return self._requireType(type).isVariadicType(type) ? acc + 1 : acc;\n }, 0);\n var valueTypes = types.length - prefixTypes;\n\n var prefix = bytes.slice(0, prefixTypes * 64);\n bytes = bytes.slice(prefixTypes * 64);\n var value = bytes.slice(0, valueTypes * 64);\n var suffix = bytes.slice(valueTypes * 64);\n return new SolidityParam(value, prefix, suffix); \n};\n\n/**\n * Should be used to transform plain param of given type to SolidityParam\n *\n * @method _formatInput\n * @param {String} type of param\n * @param {Object} plain param\n * @return {SolidityParam}\n */\nSolidityCoder.prototype._formatInput = function (type, param) {\n return this._requireType(type).formatInput(param, isArrayType(type));\n};\n\n/**\n * Should be used to encode plain param\n *\n * @method encodeParam\n * @param {String} type\n * @param {Object} plain param\n * @return {String} encoded plain param\n */\nSolidityCoder.prototype.encodeParam = function (type, param) {\n return this._formatInput(type, param).encode();\n};\n\n/**\n * Should be used to encode list of params\n *\n * @method encodeParams\n * @param {Array} types\n * @param {Array} params\n * @return {String} encoded list of params\n */\nSolidityCoder.prototype.encodeParams = function (types, params) {\n var self = this;\n return types.map(function (type, index) {\n return self._formatInput(type, params[index]);\n }).reduce(function (acc, solidityParam) {\n acc.append(solidityParam);\n return acc;\n }, new SolidityParam()).encode();\n};\n\n/**\n * Should be used to transform SolidityParam to plain param\n *\n * @method _formatOutput\n * @param {String} type\n * @param {SolidityParam} param\n * @return {Object} plain param\n */\nSolidityCoder.prototype._formatOutput = function (type, param) {\n return this._requireType(type).formatOutput(param, isArrayType(type));\n};\n\n/**\n * Should be used to decode bytes to plain param\n *\n * @method decodeParam\n * @param {String} type\n * @param {String} bytes\n * @return {Object} plain param\n */\nSolidityCoder.prototype.decodeParam = function (type, bytes) {\n return this._formatOutput(type, this._bytesToParam([type], bytes));\n};\n\n/**\n * Should be used to decode list of params\n *\n * @method decodeParam\n * @param {Array} types\n * @param {String} bytes\n * @return {Array} array of plain params\n */\nSolidityCoder.prototype.decodeParams = function (types, bytes) {\n var self = this;\n var param = this._bytesToParam(types, bytes);\n return types.map(function (type) {\n var solidityType = self._requireType(type);\n var p = solidityType.shiftParam(type, param);\n return solidityType.formatOutput(p, isArrayType(type));\n });\n};\n\nvar coder = new SolidityCoder([\n new SolidityType({\n name: 'address',\n match: 'strict',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputAddress\n }),\n new SolidityType({\n name: 'bool',\n match: 'strict',\n mode: 'value',\n inputFormatter: f.formatInputBool,\n outputFormatter: f.formatOutputBool\n }),\n new SolidityType({\n name: 'int',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputInt,\n }),\n new SolidityType({\n name: 'uint',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputUInt\n }),\n new SolidityType({\n name: 'bytes',\n match: 'strict',\n mode: 'bytes',\n inputFormatter: f.formatInputDynamicBytes,\n outputFormatter: f.formatOutputDynamicBytes\n }),\n new SolidityType({\n name: 'bytes',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputBytes,\n outputFormatter: f.formatOutputBytes\n }),\n new SolidityType({\n name: 'real',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputReal,\n outputFormatter: f.formatOutputReal\n }),\n new SolidityType({\n name: 'ureal',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputReal,\n outputFormatter: f.formatOutputUReal\n })\n]);\n\nmodule.exports = coder;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file formatters.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar BigNumber = require('bignumber.js');\nvar utils = require('../utils/utils');\nvar c = require('../utils/config');\nvar SolidityParam = require('./param');\n\n\n/**\n * Formats input value to byte representation of int\n * If value is negative, return it's two's complement\n * If the value is floating point, round it down\n *\n * @method formatInputInt\n * @param {String|Number|BigNumber} value that needs to be formatted\n * @returns {SolidityParam}\n */\nvar formatInputInt = function (value) {\n var padding = c.ETH_PADDING * 2;\n BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE);\n var result = utils.padLeft(utils.toTwosComplement(value).round().toString(16), padding);\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of string\n *\n * @method formatInputBytes\n * @param {String}\n * @returns {SolidityParam}\n */\nvar formatInputBytes = function (value) {\n var result = utils.fromAscii(value, c.ETH_PADDING).substr(2);\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of string\n *\n * @method formatInputDynamicBytes\n * @param {String}\n * @returns {SolidityParam}\n */\nvar formatInputDynamicBytes = function (value) {\n var result = utils.fromAscii(value, c.ETH_PADDING).substr(2);\n return new SolidityParam('', formatInputInt(value.length).value, result);\n};\n\n/**\n * Formats input value to byte representation of bool\n *\n * @method formatInputBool\n * @param {Boolean}\n * @returns {SolidityParam}\n */\nvar formatInputBool = function (value) {\n var result = '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of real\n * Values are multiplied by 2^m and encoded as integers\n *\n * @method formatInputReal\n * @param {String|Number|BigNumber}\n * @returns {SolidityParam}\n */\nvar formatInputReal = function (value) {\n return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128)));\n};\n\n/**\n * Check if input value is negative\n *\n * @method signedIsNegative\n * @param {String} value is hex format\n * @returns {Boolean} true if it is negative, otherwise false\n */\nvar signedIsNegative = function (value) {\n return (new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1)) === '1';\n};\n\n/**\n * Formats right-aligned output bytes to int\n *\n * @method formatOutputInt\n * @param {SolidityParam} param\n * @returns {BigNumber} right-aligned output bytes formatted to big number\n */\nvar formatOutputInt = function (param) {\n var value = param.value || \"0\";\n\n // check if it's negative number\n // it it is, return two's complement\n if (signedIsNegative(value)) {\n return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1);\n }\n return new BigNumber(value, 16);\n};\n\n/**\n * Formats right-aligned output bytes to uint\n *\n * @method formatOutputUInt\n * @param {SolidityParam}\n * @returns {BigNumeber} right-aligned output bytes formatted to uint\n */\nvar formatOutputUInt = function (param) {\n var value = param.value || \"0\";\n return new BigNumber(value, 16);\n};\n\n/**\n * Formats right-aligned output bytes to real\n *\n * @method formatOutputReal\n * @param {SolidityParam}\n * @returns {BigNumber} input bytes formatted to real\n */\nvar formatOutputReal = function (param) {\n return formatOutputInt(param).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/**\n * Formats right-aligned output bytes to ureal\n *\n * @method formatOutputUReal\n * @param {SolidityParam}\n * @returns {BigNumber} input bytes formatted to ureal\n */\nvar formatOutputUReal = function (param) {\n return formatOutputUInt(param).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/**\n * Should be used to format output bool\n *\n * @method formatOutputBool\n * @param {SolidityParam}\n * @returns {Boolean} right-aligned input bytes formatted to bool\n */\nvar formatOutputBool = function (param) {\n return param.value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;\n};\n\n/**\n * Should be used to format output string\n *\n * @method formatOutputBytes\n * @param {SolidityParam} left-aligned hex representation of string\n * @returns {String} ascii string\n */\nvar formatOutputBytes = function (param) {\n // length might also be important!\n return utils.toAscii(param.value);\n};\n\n/**\n * Should be used to format output string\n *\n * @method formatOutputDynamicBytes\n * @param {SolidityParam} left-aligned hex representation of string\n * @returns {String} ascii string\n */\nvar formatOutputDynamicBytes = function (param) {\n // length might also be important!\n return utils.toAscii(param.suffix);\n};\n\n/**\n * Should be used to format output address\n *\n * @method formatOutputAddress\n * @param {SolidityParam} right-aligned input bytes\n * @returns {String} address\n */\nvar formatOutputAddress = function (param) {\n var value = param.value;\n return \"0x\" + value.slice(value.length - 40, value.length);\n};\n\nmodule.exports = {\n formatInputInt: formatInputInt,\n formatInputBytes: formatInputBytes,\n formatInputDynamicBytes: formatInputDynamicBytes,\n formatInputBool: formatInputBool,\n formatInputReal: formatInputReal,\n formatOutputInt: formatOutputInt,\n formatOutputUInt: formatOutputUInt,\n formatOutputReal: formatOutputReal,\n formatOutputUReal: formatOutputUReal,\n formatOutputBool: formatOutputBool,\n formatOutputBytes: formatOutputBytes,\n formatOutputDynamicBytes: formatOutputDynamicBytes,\n formatOutputAddress: formatOutputAddress\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file param.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\n/**\n * SolidityParam object prototype.\n * Should be used when encoding, decoding solidity bytes\n */\nvar SolidityParam = function (value, prefix, suffix) {\n this.prefix = prefix || '';\n this.value = value || '';\n this.suffix = suffix || '';\n};\n\n/**\n * This method should be used to encode two params one after another\n *\n * @method append\n * @param {SolidityParam} param that it appended after this\n */\nSolidityParam.prototype.append = function (param) {\n this.prefix += param.prefix;\n this.value += param.value;\n this.suffix += param.suffix;\n};\n\n/**\n * This method should be used to encode next param in an array\n *\n * @method appendArrayElement\n * @param {SolidityParam} param that is appended to an array\n */\nSolidityParam.prototype.appendArrayElement = function (param) {\n this.suffix += param.value;\n this.prefix += param.prefix;\n // TODO: suffix not supported = it's required for nested arrays;\n};\n\n/**\n * This method should be used to create bytearrays from param\n *\n * @method encode\n * @return {String} encoded param(s)\n */\nSolidityParam.prototype.encode = function () {\n return this.prefix + this.value + this.suffix;\n};\n\n/**\n * This method should be used to shift first param from group of params\n *\n * @method shiftValue\n * @return {SolidityParam} first value param\n */\nSolidityParam.prototype.shiftValue = function () {\n var value = this.value.slice(0, 64);\n this.value = this.value.slice(64);\n return new SolidityParam(value);\n};\n\n/**\n * This method should be used to first bytes param from group of params\n *\n * @method shiftBytes\n * @return {SolidityParam} first bytes param\n */\nSolidityParam.prototype.shiftBytes = function () {\n return this.shiftArray(1); \n};\n\n/**\n * This method should be used to shift an array from group of params \n * \n * @method shiftArray\n * @param {Number} size of an array to shift\n * @return {SolidityParam} first array param\n */\nSolidityParam.prototype.shiftArray = function (length) {\n var prefix = this.prefix.slice(0, 64);\n this.prefix = this.value.slice(64);\n var suffix = this.suffix.slice(0, 64 * length);\n this.suffix = this.suffix.slice(64 * length);\n return new SolidityParam('', prefix, suffix);\n};\n\nmodule.exports = SolidityParam;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/**\n * @file utils.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\n/**\n * Returns the contstructor with matching number of arguments\n *\n * @method getConstructor\n * @param {Array} abi\n * @param {Number} numberOfArgs\n * @returns {Object} constructor function abi\n */\nvar getConstructor = function (abi, numberOfArgs) {\n return abi.filter(function (f) {\n return f.type === 'constructor' && f.inputs.length === numberOfArgs;\n })[0];\n};\n\nmodule.exports = {\n getConstructor: getConstructor\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file abi.js\n * @author Marek Kotewicz \n * @author Gav Wood \n * @date 2014\n */\n\nvar coder = require('./coder');\nvar utils = require('./utils');\n\nvar formatConstructorParams = function (abi, params) {\n var constructor = utils.getConstructor(abi, params.length);\n if (!constructor) {\n if (params.length > 0) {\n console.warn(\"didn't found matching constructor, using default one\");\n }\n return '';\n }\n\n return coder.encodeParams(constructor.inputs.map(function (input) {\n return input.type;\n }), params);\n};\n\nmodule.exports = {\n formatConstructorParams: formatConstructorParams\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file coder.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar BigNumber = require('bignumber.js');\nvar utils = require('../utils/utils');\nvar f = require('./formatters');\nvar SolidityParam = require('./param');\n\n/**\n * Should be used to check if a type is an array type\n *\n * @method isArrayType\n * @param {String} type\n * @return {Bool} true is the type is an array, otherwise false\n */\nvar isArrayType = function (type) {\n return type.slice(-2) === '[]';\n};\n\n/**\n * SolidityType prototype is used to encode/decode solidity params of certain type\n */\nvar SolidityType = function (config) {\n this._name = config.name;\n this._match = config.match;\n this._mode = config.mode;\n this._inputFormatter = config.inputFormatter;\n this._outputFormatter = config.outputFormatter;\n};\n\n/**\n * Should be used to determine if this SolidityType do match given type\n *\n * @method isType\n * @param {String} name\n * @return {Bool} true if type match this SolidityType, otherwise false\n */\nSolidityType.prototype.isType = function (name) {\n if (this._match === 'strict') {\n return this._name === name || (name.indexOf(this._name) === 0 && name.slice(this._name.length) === '[]');\n } else if (this._match === 'prefix') {\n // TODO better type detection!\n return name.indexOf(this._name) === 0;\n }\n};\n\n/**\n * Should be used to transform plain param to SolidityParam object\n *\n * @method formatInput\n * @param {Object} param - plain object, or an array of objects\n * @param {Bool} arrayType - true if a param should be encoded as an array\n * @return {SolidityParam} encoded param wrapped in SolidityParam object \n */\nSolidityType.prototype.formatInput = function (param, arrayType) {\n if (utils.isArray(param) && arrayType) { // TODO: should fail if this two are not the same\n var self = this;\n return param.map(function (p) {\n return self._inputFormatter(p);\n }).reduce(function (acc, current) {\n return acc.combine(current);\n }, f.formatInputInt(param.length)).withOffset(32);\n } \n return this._inputFormatter(param);\n};\n\n/**\n * Should be used to transoform SolidityParam to plain param\n *\n * @method formatOutput\n * @param {SolidityParam} byteArray\n * @param {Bool} arrayType - true if a param should be decoded as an array\n * @return {Object} plain decoded param\n */\nSolidityType.prototype.formatOutput = function (param, arrayType) {\n if (arrayType) {\n // let's assume, that we solidity will never return long arrays :P \n var result = [];\n var length = new BigNumber(param.dynamicPart().slice(0, 64), 16);\n for (var i = 0; i < length * 64; i += 64) {\n result.push(this._outputFormatter(new SolidityParam(param.dynamicPart().substr(i + 64, 64))));\n }\n return result;\n }\n return this._outputFormatter(param);\n};\n\n/**\n * Should be used to slice single param from bytes\n *\n * @method sliceParam\n * @param {String} bytes\n * @param {Number} index of param to slice\n * @param {String} type\n * @returns {SolidityParam} param\n */\nSolidityType.prototype.sliceParam = function (bytes, index, type) {\n if (this._mode === 'bytes') {\n return SolidityParam.decodeBytes(bytes, index);\n } else if (isArrayType(type)) {\n return SolidityParam.decodeArray(bytes, index);\n }\n return SolidityParam.decodeParam(bytes, index);\n};\n\n/**\n * SolidityCoder prototype should be used to encode/decode solidity params of any type\n */\nvar SolidityCoder = function (types) {\n this._types = types;\n};\n\n/**\n * This method should be used to transform type to SolidityType\n *\n * @method _requireType\n * @param {String} type\n * @returns {SolidityType} \n * @throws {Error} throws if no matching type is found\n */\nSolidityCoder.prototype._requireType = function (type) {\n var solidityType = this._types.filter(function (t) {\n return t.isType(type);\n })[0];\n\n if (!solidityType) {\n throw Error('invalid solidity type!: ' + type);\n }\n\n return solidityType;\n};\n\n/**\n * Should be used to transform plain param of given type to SolidityParam\n *\n * @method _formatInput\n * @param {String} type of param\n * @param {Object} plain param\n * @return {SolidityParam}\n */\nSolidityCoder.prototype._formatInput = function (type, param) {\n return this._requireType(type).formatInput(param, isArrayType(type));\n};\n\n/**\n * Should be used to encode plain param\n *\n * @method encodeParam\n * @param {String} type\n * @param {Object} plain param\n * @return {String} encoded plain param\n */\nSolidityCoder.prototype.encodeParam = function (type, param) {\n return this._formatInput(type, param).encode();\n};\n\n/**\n * Should be used to encode list of params\n *\n * @method encodeParams\n * @param {Array} types\n * @param {Array} params\n * @return {String} encoded list of params\n */\nSolidityCoder.prototype.encodeParams = function (types, params) {\n var self = this;\n var solidityParams = types.map(function (type, index) {\n return self._formatInput(type, params[index]);\n });\n\n return SolidityParam.encodeList(solidityParams);\n};\n\n/**\n * Should be used to decode bytes to plain param\n *\n * @method decodeParam\n * @param {String} type\n * @param {String} bytes\n * @return {Object} plain param\n */\nSolidityCoder.prototype.decodeParam = function (type, bytes) {\n return this.decodeParams([type], bytes)[0];\n};\n\n/**\n * Should be used to decode list of params\n *\n * @method decodeParam\n * @param {Array} types\n * @param {String} bytes\n * @return {Array} array of plain params\n */\nSolidityCoder.prototype.decodeParams = function (types, bytes) {\n var self = this;\n return types.map(function (type, index) {\n var solidityType = self._requireType(type);\n var p = solidityType.sliceParam(bytes, index, type);\n return solidityType.formatOutput(p, isArrayType(type));\n });\n};\n\nvar coder = new SolidityCoder([\n new SolidityType({\n name: 'address',\n match: 'strict',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputAddress\n }),\n new SolidityType({\n name: 'bool',\n match: 'strict',\n mode: 'value',\n inputFormatter: f.formatInputBool,\n outputFormatter: f.formatOutputBool\n }),\n new SolidityType({\n name: 'int',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputInt,\n }),\n new SolidityType({\n name: 'uint',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputUInt\n }),\n new SolidityType({\n name: 'bytes',\n match: 'strict',\n mode: 'bytes',\n inputFormatter: f.formatInputDynamicBytes,\n outputFormatter: f.formatOutputDynamicBytes\n }),\n new SolidityType({\n name: 'bytes',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputBytes,\n outputFormatter: f.formatOutputBytes\n }),\n new SolidityType({\n name: 'real',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputReal,\n outputFormatter: f.formatOutputReal\n }),\n new SolidityType({\n name: 'ureal',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputReal,\n outputFormatter: f.formatOutputUReal\n })\n]);\n\nmodule.exports = coder;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file formatters.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar BigNumber = require('bignumber.js');\nvar utils = require('../utils/utils');\nvar c = require('../utils/config');\nvar SolidityParam = require('./param');\n\n\n/**\n * Formats input value to byte representation of int\n * If value is negative, return it's two's complement\n * If the value is floating point, round it down\n *\n * @method formatInputInt\n * @param {String|Number|BigNumber} value that needs to be formatted\n * @returns {SolidityParam}\n */\nvar formatInputInt = function (value) {\n var padding = c.ETH_PADDING * 2;\n BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE);\n var result = utils.padLeft(utils.toTwosComplement(value).round().toString(16), padding);\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of string\n *\n * @method formatInputBytes\n * @param {String}\n * @returns {SolidityParam}\n */\nvar formatInputBytes = function (value) {\n var result = utils.fromAscii(value, c.ETH_PADDING).substr(2);\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of string\n *\n * @method formatInputDynamicBytes\n * @param {String}\n * @returns {SolidityParam}\n */\nvar formatInputDynamicBytes = function (value) {\n var result = utils.fromAscii(value, c.ETH_PADDING).substr(2);\n return new SolidityParam(formatInputInt(value.length).value + result, 32);\n};\n\n/**\n * Formats input value to byte representation of bool\n *\n * @method formatInputBool\n * @param {Boolean}\n * @returns {SolidityParam}\n */\nvar formatInputBool = function (value) {\n var result = '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of real\n * Values are multiplied by 2^m and encoded as integers\n *\n * @method formatInputReal\n * @param {String|Number|BigNumber}\n * @returns {SolidityParam}\n */\nvar formatInputReal = function (value) {\n return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128)));\n};\n\n/**\n * Check if input value is negative\n *\n * @method signedIsNegative\n * @param {String} value is hex format\n * @returns {Boolean} true if it is negative, otherwise false\n */\nvar signedIsNegative = function (value) {\n return (new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1)) === '1';\n};\n\n/**\n * Formats right-aligned output bytes to int\n *\n * @method formatOutputInt\n * @param {SolidityParam} param\n * @returns {BigNumber} right-aligned output bytes formatted to big number\n */\nvar formatOutputInt = function (param) {\n var value = param.staticPart() || \"0\";\n\n // check if it's negative number\n // it it is, return two's complement\n if (signedIsNegative(value)) {\n return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1);\n }\n return new BigNumber(value, 16);\n};\n\n/**\n * Formats right-aligned output bytes to uint\n *\n * @method formatOutputUInt\n * @param {SolidityParam}\n * @returns {BigNumeber} right-aligned output bytes formatted to uint\n */\nvar formatOutputUInt = function (param) {\n var value = param.staticPart() || \"0\";\n return new BigNumber(value, 16);\n};\n\n/**\n * Formats right-aligned output bytes to real\n *\n * @method formatOutputReal\n * @param {SolidityParam}\n * @returns {BigNumber} input bytes formatted to real\n */\nvar formatOutputReal = function (param) {\n return formatOutputInt(param).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/**\n * Formats right-aligned output bytes to ureal\n *\n * @method formatOutputUReal\n * @param {SolidityParam}\n * @returns {BigNumber} input bytes formatted to ureal\n */\nvar formatOutputUReal = function (param) {\n return formatOutputUInt(param).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/**\n * Should be used to format output bool\n *\n * @method formatOutputBool\n * @param {SolidityParam}\n * @returns {Boolean} right-aligned input bytes formatted to bool\n */\nvar formatOutputBool = function (param) {\n return param.staticPart() === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;\n};\n\n/**\n * Should be used to format output string\n *\n * @method formatOutputBytes\n * @param {SolidityParam} left-aligned hex representation of string\n * @returns {String} ascii string\n */\nvar formatOutputBytes = function (param) {\n // length might also be important!\n return utils.toAscii(param.staticPart());\n};\n\n/**\n * Should be used to format output string\n *\n * @method formatOutputDynamicBytes\n * @param {SolidityParam} left-aligned hex representation of string\n * @returns {String} ascii string\n */\nvar formatOutputDynamicBytes = function (param) {\n // length might also be important!\n return utils.toAscii(param.dynamicPart().slice(64));\n};\n\n/**\n * Should be used to format output address\n *\n * @method formatOutputAddress\n * @param {SolidityParam} right-aligned input bytes\n * @returns {String} address\n */\nvar formatOutputAddress = function (param) {\n var value = param.staticPart();\n return \"0x\" + value.slice(value.length - 40, value.length);\n};\n\nmodule.exports = {\n formatInputInt: formatInputInt,\n formatInputBytes: formatInputBytes,\n formatInputDynamicBytes: formatInputDynamicBytes,\n formatInputBool: formatInputBool,\n formatInputReal: formatInputReal,\n formatOutputInt: formatOutputInt,\n formatOutputUInt: formatOutputUInt,\n formatOutputReal: formatOutputReal,\n formatOutputUReal: formatOutputUReal,\n formatOutputBool: formatOutputBool,\n formatOutputBytes: formatOutputBytes,\n formatOutputDynamicBytes: formatOutputDynamicBytes,\n formatOutputAddress: formatOutputAddress\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file param.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar utils = require('../utils/utils');\n\n/**\n * SolidityParam object prototype.\n * Should be used when encoding, decoding solidity bytes\n */\nvar SolidityParam = function (value, offset) {\n this.value = value || '';\n this.offset = offset; // offset in bytes\n};\n\n/**\n * This method should be used to get length of params's dynamic part\n * \n * @method dynamicPartLength\n * @returns {Number} length of dynamic part (in bytes)\n */\nSolidityParam.prototype.dynamicPartLength = function () {\n return this.dynamicPart().length / 2;\n};\n\n/**\n * This method should be used to create copy of solidity param with different offset\n *\n * @method withOffset\n * @param {Number} offset length in bytes\n * @returns {SolidityParam} new solidity param with applied offset\n */\nSolidityParam.prototype.withOffset = function (offset) {\n return new SolidityParam(this.value, offset);\n};\n\n/**\n * This method should be used to combine solidity params together\n * eg. when appending an array\n *\n * @method combine\n * @param {SolidityParam} param with which we should combine\n * @param {SolidityParam} result of combination\n */\nSolidityParam.prototype.combine = function (param) {\n return new SolidityParam(this.value + param.value); \n};\n\n/**\n * This method should be called to check if param has dynamic size.\n * If it has, it returns true, otherwise false\n *\n * @method isDynamic\n * @returns {Boolean}\n */\nSolidityParam.prototype.isDynamic = function () {\n return this.value.length > 64;\n};\n\n/**\n * This method should be called to transform offset to bytes\n *\n * @method offsetAsBytes\n * @returns {String} bytes representation of offset\n */\nSolidityParam.prototype.offsetAsBytes = function () {\n return !this.isDynamic() ? '' : utils.padLeft(utils.toTwosComplement(this.offset).toString(16), 64);\n};\n\n/**\n * This method should be called to get static part of param\n *\n * @method staticPart\n * @returns {String} offset if it is a dynamic param, otherwise value\n */\nSolidityParam.prototype.staticPart = function () {\n if (!this.isDynamic()) {\n return this.value; \n } \n return this.offsetAsBytes();\n};\n\n/**\n * This method should be called to get dynamic part of param\n *\n * @method dynamicPart\n * @returns {String} returns a value if it is a dynamic param, otherwise empty string\n */\nSolidityParam.prototype.dynamicPart = function () {\n return this.isDynamic() ? this.value : '';\n};\n\n/**\n * This method should be called to encode param\n *\n * @method encode\n * @returns {String}\n */\nSolidityParam.prototype.encode = function () {\n return this.staticPart() + this.dynamicPart();\n};\n\n/**\n * This method should be called to encode array of params\n *\n * @method encodeList\n * @param {Array[SolidityParam]} params\n * @returns {String}\n */\nSolidityParam.encodeList = function (params) {\n \n // updating offsets\n var totalOffset = params.length * 32;\n var offsetParams = params.map(function (param) {\n if (!param.isDynamic()) {\n return param;\n }\n var offset = totalOffset;\n totalOffset += param.dynamicPartLength();\n return param.withOffset(offset);\n });\n\n // encode everything!\n return offsetParams.reduce(function (result, param) {\n return result + param.dynamicPart();\n }, offsetParams.reduce(function (result, param) {\n return result + param.staticPart();\n }, ''));\n};\n\n/**\n * This method should be used to decode plain (static) solidity param at given index\n *\n * @method decodeParam\n * @param {String} bytes\n * @param {Number} index\n * @returns {SolidityParam}\n */\nSolidityParam.decodeParam = function (bytes, index) {\n index = index || 0;\n return new SolidityParam(bytes.substr(index * 64, 64)); \n};\n\n/**\n * This method should be called to get offset value from bytes at given index\n *\n * @method getOffset\n * @param {String} bytes\n * @param {Number} index\n * @returns {Number} offset as number\n */\nvar getOffset = function (bytes, index) {\n // we can do this cause offset is rather small\n return parseInt('0x' + bytes.substr(index * 64, 64));\n};\n\n/**\n * This method should be called to decode solidity bytes param at given index\n *\n * @method decodeBytes\n * @param {String} bytes\n * @param {Number} index\n * @returns {SolidityParam}\n */\nSolidityParam.decodeBytes = function (bytes, index) {\n index = index || 0;\n //TODO add support for strings longer than 32 bytes\n //var length = parseInt('0x' + bytes.substr(offset * 64, 64));\n\n var offset = getOffset(bytes, index);\n\n // 2 * , cause we also parse length\n return new SolidityParam(bytes.substr(offset * 2, 2 * 64));\n};\n\n/**\n * This method should be used to decode solidity array at given index\n *\n * @method decodeArray\n * @param {String} bytes\n * @param {Number} index\n * @returns {SolidityParam}\n */\nSolidityParam.decodeArray = function (bytes, index) {\n index = index || 0;\n var offset = getOffset(bytes, index);\n var length = parseInt('0x' + bytes.substr(offset * 2, 64));\n return new SolidityParam(bytes.substr(offset * 2, (length + 1) * 64));\n};\n\nmodule.exports = SolidityParam;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/**\n * @file utils.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\n/**\n * Returns the contstructor with matching number of arguments\n *\n * @method getConstructor\n * @param {Array} abi\n * @param {Number} numberOfArgs\n * @returns {Object} constructor function abi\n */\nvar getConstructor = function (abi, numberOfArgs) {\n return abi.filter(function (f) {\n return f.type === 'constructor' && f.inputs.length === numberOfArgs;\n })[0];\n};\n\n//var getSupremeType = function (type) {\n //return type.substr(0, type.indexOf('[')) + ']';\n//};\n\n\nmodule.exports = {\n getConstructor: getConstructor\n};\n\n", "'use strict';\n\n// go env doesn't have and need XMLHttpRequest\nif (typeof XMLHttpRequest === 'undefined') {\n exports.XMLHttpRequest = {};\n} else {\n exports.XMLHttpRequest = XMLHttpRequest; // jshint ignore:line\n}\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file config.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\n/**\n * Utils\n * \n * @module utils\n */\n\n/**\n * Utility functions\n * \n * @class [utils] config\n * @constructor\n */\n\n/// required to define ETH_BIGNUMBER_ROUNDING_MODE\nvar BigNumber = require('bignumber.js');\n\nvar ETH_UNITS = [ \n 'wei', \n 'Kwei', \n 'Mwei', \n 'Gwei', \n 'szabo', \n 'finney', \n 'ether', \n 'grand', \n 'Mether', \n 'Gether', \n 'Tether', \n 'Pether', \n 'Eether', \n 'Zether', \n 'Yether', \n 'Nether', \n 'Dether', \n 'Vether', \n 'Uether' \n];\n\nmodule.exports = {\n ETH_PADDING: 32,\n ETH_SIGNATURE_LENGTH: 4,\n ETH_UNITS: ETH_UNITS,\n ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN },\n ETH_POLLING_TIMEOUT: 1000,\n defaultBlock: 'latest',\n defaultAccount: undefined\n};\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file utils.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\n/**\n * Utils\n * \n * @module utils\n */\n\n/**\n * Utility functions\n * \n * @class [utils] utils\n * @constructor\n */\n\nvar BigNumber = require('bignumber.js');\n\nvar unitMap = {\n 'wei': '1',\n 'kwei': '1000',\n 'ada': '1000',\n 'mwei': '1000000',\n 'babbage': '1000000',\n 'gwei': '1000000000',\n 'shannon': '1000000000',\n 'szabo': '1000000000000',\n 'finney': '1000000000000000',\n 'ether': '1000000000000000000',\n 'kether': '1000000000000000000000',\n 'grand': '1000000000000000000000',\n 'einstein': '1000000000000000000000',\n 'mether': '1000000000000000000000000',\n 'gether': '1000000000000000000000000000',\n 'tether': '1000000000000000000000000000000'\n};\n\n/**\n * Should be called to pad string to expected length\n *\n * @method padLeft\n * @param {String} string to be padded\n * @param {Number} characters that result string should have\n * @param {String} sign, by default 0\n * @returns {String} right aligned string\n */\nvar padLeft = function (string, chars, sign) {\n return new Array(chars - string.length + 1).join(sign ? sign : \"0\") + string;\n};\n\n/** \n * Should be called to get sting from it's hex representation\n *\n * @method toAscii\n * @param {String} string in hex\n * @returns {String} ascii string representation of hex value\n */\nvar toAscii = function(hex) {\n// Find termination\n var str = \"\";\n var i = 0, l = hex.length;\n if (hex.substring(0, 2) === '0x') {\n i = 2;\n }\n for (; i < l; i+=2) {\n var code = parseInt(hex.substr(i, 2), 16);\n if (code === 0) {\n break;\n }\n\n str += String.fromCharCode(code);\n }\n\n return str;\n};\n \n/**\n * Shold be called to get hex representation (prefixed by 0x) of ascii string \n *\n * @method toHexNative\n * @param {String} string\n * @returns {String} hex representation of input string\n */\nvar toHexNative = function(str) {\n var hex = \"\";\n for(var i = 0; i < str.length; i++) {\n var n = str.charCodeAt(i).toString(16);\n hex += n.length < 2 ? '0' + n : n;\n }\n\n return hex;\n};\n\n/**\n * Shold be called to get hex representation (prefixed by 0x) of ascii string \n *\n * @method fromAscii\n * @param {String} string\n * @param {Number} optional padding\n * @returns {String} hex representation of input string\n */\nvar fromAscii = function(str, pad) {\n pad = pad === undefined ? 0 : pad;\n var hex = toHexNative(str);\n while (hex.length < pad*2)\n hex += \"00\";\n return \"0x\" + hex;\n};\n\n/**\n * Should be used to create full function/event name from json abi\n *\n * @method transformToFullName\n * @param {Object} json-abi\n * @return {String} full fnction/event name\n */\nvar transformToFullName = function (json) {\n if (json.name.indexOf('(') !== -1) {\n return json.name;\n }\n\n var typeName = json.inputs.map(function(i){return i.type; }).join();\n return json.name + '(' + typeName + ')';\n};\n\n/**\n * Should be called to get display name of contract function\n * \n * @method extractDisplayName\n * @param {String} name of function/event\n * @returns {String} display name for function/event eg. multiply(uint256) -> multiply\n */\nvar extractDisplayName = function (name) {\n var length = name.indexOf('('); \n return length !== -1 ? name.substr(0, length) : name;\n};\n\n/// @returns overloaded part of function/event name\nvar extractTypeName = function (name) {\n /// TODO: make it invulnerable\n var length = name.indexOf('(');\n return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)).replace(' ', '') : \"\";\n};\n\n/**\n * Converts value to it's decimal representation in string\n *\n * @method toDecimal\n * @param {String|Number|BigNumber}\n * @return {String}\n */\nvar toDecimal = function (value) {\n return toBigNumber(value).toNumber();\n};\n\n/**\n * Converts value to it's hex representation\n *\n * @method fromDecimal\n * @param {String|Number|BigNumber}\n * @return {String}\n */\nvar fromDecimal = function (value) {\n var number = toBigNumber(value);\n var result = number.toString(16);\n\n return number.lessThan(0) ? '-0x' + result.substr(1) : '0x' + result;\n};\n\n/**\n * Auto converts any given value into it's hex representation.\n *\n * And even stringifys objects before.\n *\n * @method toHex\n * @param {String|Number|BigNumber|Object}\n * @return {String}\n */\nvar toHex = function (val) {\n /*jshint maxcomplexity:7 */\n\n if (isBoolean(val))\n return fromDecimal(+val);\n\n if (isBigNumber(val))\n return fromDecimal(val);\n\n if (isObject(val))\n return fromAscii(JSON.stringify(val));\n\n // if its a negative number, pass it through fromDecimal\n if (isString(val)) {\n if (val.indexOf('-0x') === 0)\n return fromDecimal(val);\n else if (!isFinite(val))\n return fromAscii(val);\n }\n\n return fromDecimal(val);\n};\n\n/**\n * Returns value of unit in Wei\n *\n * @method getValueOfUnit\n * @param {String} unit the unit to convert to, default ether\n * @returns {BigNumber} value of the unit (in Wei)\n * @throws error if the unit is not correct:w\n */\nvar getValueOfUnit = function (unit) {\n unit = unit ? unit.toLowerCase() : 'ether';\n var unitValue = unitMap[unit];\n if (unitValue === undefined) {\n throw new Error('This unit doesn\\'t exists, please use the one of the following units' + JSON.stringify(unitMap, null, 2));\n }\n return new BigNumber(unitValue, 10);\n};\n\n/**\n * Takes a number of wei and converts it to any other ether unit.\n *\n * Possible units are:\n * - kwei/ada\n * - mwei/babbage\n * - gwei/shannon\n * - szabo\n * - finney\n * - ether\n * - kether/grand/einstein\n * - mether\n * - gether\n * - tether\n *\n * @method fromWei\n * @param {Number|String} number can be a number, number string or a HEX of a decimal\n * @param {String} unit the unit to convert to, default ether\n * @return {String|Object} When given a BigNumber object it returns one as well, otherwise a number\n*/\nvar fromWei = function(number, unit) {\n var returnValue = toBigNumber(number).dividedBy(getValueOfUnit(unit));\n\n return isBigNumber(number) ? returnValue : returnValue.toString(10); \n};\n\n/**\n * Takes a number of a unit and converts it to wei.\n *\n * Possible units are:\n * - kwei/ada\n * - mwei/babbage\n * - gwei/shannon\n * - szabo\n * - finney\n * - ether\n * - kether/grand/einstein\n * - mether\n * - gether\n * - tether\n *\n * @method toWei\n * @param {Number|String|BigNumber} number can be a number, number string or a HEX of a decimal\n * @param {String} unit the unit to convert from, default ether\n * @return {String|Object} When given a BigNumber object it returns one as well, otherwise a number\n*/\nvar toWei = function(number, unit) {\n var returnValue = toBigNumber(number).times(getValueOfUnit(unit));\n\n return isBigNumber(number) ? returnValue : returnValue.toString(10); \n};\n\n/**\n * Takes an input and transforms it into an bignumber\n *\n * @method toBigNumber\n * @param {Number|String|BigNumber} a number, string, HEX string or BigNumber\n * @return {BigNumber} BigNumber\n*/\nvar toBigNumber = function(number) {\n /*jshint maxcomplexity:5 */\n number = number || 0;\n if (isBigNumber(number))\n return number;\n\n if (isString(number) && (number.indexOf('0x') === 0 || number.indexOf('-0x') === 0)) {\n return new BigNumber(number.replace('0x',''), 16);\n }\n \n return new BigNumber(number.toString(10), 10);\n};\n\n/**\n * Takes and input transforms it into bignumber and if it is negative value, into two's complement\n *\n * @method toTwosComplement\n * @param {Number|String|BigNumber}\n * @return {BigNumber}\n */\nvar toTwosComplement = function (number) {\n var bigNumber = toBigNumber(number);\n if (bigNumber.lessThan(0)) {\n return new BigNumber(\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\", 16).plus(bigNumber).plus(1);\n }\n return bigNumber;\n};\n\n/**\n * Checks if the given string is strictly an address\n *\n * @method isStrictAddress\n * @param {String} address the given HEX adress\n * @return {Boolean}\n*/\nvar isStrictAddress = function (address) {\n return /^0x[0-9a-f]{40}$/.test(address);\n};\n\n/**\n * Checks if the given string is an address\n *\n * @method isAddress\n * @param {String} address the given HEX adress\n * @return {Boolean}\n*/\nvar isAddress = function (address) {\n return /^(0x)?[0-9a-f]{40}$/.test(address);\n};\n\n/**\n * Transforms given string to valid 20 bytes-length addres with 0x prefix\n *\n * @method toAddress\n * @param {String} address\n * @return {String} formatted address\n */\nvar toAddress = function (address) {\n if (isStrictAddress(address)) {\n return address;\n }\n \n if (/^[0-9a-f]{40}$/.test(address)) {\n return '0x' + address;\n }\n\n return '0x' + padLeft(toHex(address).substr(2), 40);\n};\n\n/**\n * Returns true if object is BigNumber, otherwise false\n *\n * @method isBigNumber\n * @param {Object}\n * @return {Boolean} \n */\nvar isBigNumber = function (object) {\n return object instanceof BigNumber ||\n (object && object.constructor && object.constructor.name === 'BigNumber');\n};\n\n/**\n * Returns true if object is string, otherwise false\n * \n * @method isString\n * @param {Object}\n * @return {Boolean}\n */\nvar isString = function (object) {\n return typeof object === 'string' ||\n (object && object.constructor && object.constructor.name === 'String');\n};\n\n/**\n * Returns true if object is function, otherwise false\n *\n * @method isFunction\n * @param {Object}\n * @return {Boolean}\n */\nvar isFunction = function (object) {\n return typeof object === 'function';\n};\n\n/**\n * Returns true if object is Objet, otherwise false\n *\n * @method isObject\n * @param {Object}\n * @return {Boolean}\n */\nvar isObject = function (object) {\n return typeof object === 'object';\n};\n\n/**\n * Returns true if object is boolean, otherwise false\n *\n * @method isBoolean\n * @param {Object}\n * @return {Boolean}\n */\nvar isBoolean = function (object) {\n return typeof object === 'boolean';\n};\n\n/**\n * Returns true if object is array, otherwise false\n *\n * @method isArray\n * @param {Object}\n * @return {Boolean}\n */\nvar isArray = function (object) {\n return object instanceof Array; \n};\n\n/**\n * Returns true if given string is valid json object\n * \n * @method isJson\n * @param {String}\n * @return {Boolean}\n */\nvar isJson = function (str) {\n try {\n return !!JSON.parse(str);\n } catch (e) {\n return false;\n }\n};\n\nmodule.exports = {\n padLeft: padLeft,\n toHex: toHex,\n toDecimal: toDecimal,\n fromDecimal: fromDecimal,\n toAscii: toAscii,\n fromAscii: fromAscii,\n transformToFullName: transformToFullName,\n extractDisplayName: extractDisplayName,\n extractTypeName: extractTypeName,\n toWei: toWei,\n fromWei: fromWei,\n toBigNumber: toBigNumber,\n toTwosComplement: toTwosComplement,\n toAddress: toAddress,\n isBigNumber: isBigNumber,\n isStrictAddress: isStrictAddress,\n isAddress: isAddress,\n isFunction: isFunction,\n isString: isString,\n isObject: isObject,\n isBoolean: isBoolean,\n isArray: isArray,\n isJson: isJson\n};\n\n", - "module.exports={\n \"version\": \"0.3.3\"\n}\n", + "module.exports={\n \"version\": \"0.3.6\"\n}\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file web3.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * Gav Wood \n * @date 2014\n */\n\nvar version = require('./version.json');\nvar net = require('./web3/net');\nvar eth = require('./web3/eth');\nvar db = require('./web3/db');\nvar shh = require('./web3/shh');\nvar watches = require('./web3/watches');\nvar Filter = require('./web3/filter');\nvar utils = require('./utils/utils');\nvar formatters = require('./web3/formatters');\nvar RequestManager = require('./web3/requestmanager');\nvar c = require('./utils/config');\nvar Method = require('./web3/method');\nvar Property = require('./web3/property');\n\nvar web3Methods = [\n new Method({\n name: 'sha3',\n call: 'web3_sha3',\n params: 1\n })\n];\n\nvar web3Properties = [\n new Property({\n name: 'version.client',\n getter: 'web3_clientVersion'\n }),\n new Property({\n name: 'version.network',\n getter: 'net_version',\n inputFormatter: utils.toDecimal\n }),\n new Property({\n name: 'version.ethereum',\n getter: 'eth_protocolVersion',\n inputFormatter: utils.toDecimal\n }),\n new Property({\n name: 'version.whisper',\n getter: 'shh_version',\n inputFormatter: utils.toDecimal\n })\n];\n\n/// creates methods in a given object based on method description on input\n/// setups api calls for these methods\nvar setupMethods = function (obj, methods) {\n methods.forEach(function (method) {\n method.attachToObject(obj);\n });\n};\n\n/// creates properties in a given object based on properties description on input\n/// setups api calls for these properties\nvar setupProperties = function (obj, properties) {\n properties.forEach(function (property) {\n property.attachToObject(obj);\n });\n};\n\n/// setups web3 object, and it's in-browser executed methods\nvar web3 = {};\nweb3.providers = {};\nweb3.version = {};\nweb3.version.api = version.version;\nweb3.eth = {};\n\n/*jshint maxparams:4 */\nweb3.eth.filter = function (fil, eventParams, options, formatter) {\n\n // if its event, treat it differently\n // TODO: simplify and remove\n if (fil._isEvent) {\n return fil(eventParams, options);\n }\n\n // what outputLogFormatter? that's wrong\n //return new Filter(fil, watches.eth(), formatters.outputLogFormatter);\n return new Filter(fil, watches.eth(), formatter || formatters.outputLogFormatter);\n};\n/*jshint maxparams:3 */\n\nweb3.shh = {};\nweb3.shh.filter = function (fil) {\n return new Filter(fil, watches.shh(), formatters.outputPostFormatter);\n};\nweb3.net = {};\nweb3.db = {};\nweb3.setProvider = function (provider) {\n RequestManager.getInstance().setProvider(provider);\n};\nweb3.reset = function () {\n RequestManager.getInstance().reset();\n c.defaultBlock = 'latest';\n c.defaultAccount = undefined;\n};\nweb3.toHex = utils.toHex;\nweb3.toAscii = utils.toAscii;\nweb3.fromAscii = utils.fromAscii;\nweb3.toDecimal = utils.toDecimal;\nweb3.fromDecimal = utils.fromDecimal;\nweb3.toBigNumber = utils.toBigNumber;\nweb3.toWei = utils.toWei;\nweb3.fromWei = utils.fromWei;\nweb3.isAddress = utils.isAddress;\n\n// ADD defaultblock\nObject.defineProperty(web3.eth, 'defaultBlock', {\n get: function () {\n return c.defaultBlock;\n },\n set: function (val) {\n c.defaultBlock = val;\n return val;\n }\n});\n\nObject.defineProperty(web3.eth, 'defaultAccount', {\n get: function () {\n return c.defaultAccount;\n },\n set: function (val) {\n c.defaultAccount = val;\n return val;\n }\n});\n\n/// setups all api methods\nsetupMethods(web3, web3Methods);\nsetupProperties(web3, web3Properties);\nsetupMethods(web3.net, net.methods);\nsetupProperties(web3.net, net.properties);\nsetupMethods(web3.eth, eth.methods);\nsetupProperties(web3.eth, eth.properties);\nsetupMethods(web3.db, db.methods);\nsetupMethods(web3.shh, shh.methods);\n\nmodule.exports = web3;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file contract.js\n * @author Marek Kotewicz \n * @date 2014\n */\n\nvar web3 = require('../web3'); \nvar solAbi = require('../solidity/abi');\nvar utils = require('../utils/utils');\nvar SolidityEvent = require('./event');\nvar SolidityFunction = require('./function');\n\nvar addFunctionsToContract = function (contract, desc) {\n desc.filter(function (json) {\n return json.type === 'function';\n }).map(function (json) {\n return new SolidityFunction(json, contract.address);\n }).forEach(function (f) {\n f.attachToContract(contract);\n });\n};\n\nvar addEventsToContract = function (contract, desc) {\n desc.filter(function (json) {\n return json.type === 'event';\n }).map(function (json) {\n return new SolidityEvent(json, contract.address);\n }).forEach(function (e) {\n e.attachToContract(contract);\n });\n};\n\n/**\n * This method should be called when we want to call / transact some solidity method from javascript\n * it returns an object which has same methods available as solidity contract description\n * usage example: \n *\n * var abi = [{\n * name: 'myMethod',\n * inputs: [{ name: 'a', type: 'string' }],\n * outputs: [{name: 'd', type: 'string' }]\n * }]; // contract abi\n *\n * var MyContract = web3.eth.contract(abi); // creation of contract prototype\n *\n * var contractInstance = new MyContract('0x0123123121');\n *\n * contractInstance.myMethod('this is test string param for call'); // myMethod call (implicit, default)\n * contractInstance.call().myMethod('this is test string param for call'); // myMethod call (explicit)\n * contractInstance.sendTransaction().myMethod('this is test string param for transact'); // myMethod sendTransaction\n *\n * @param abi - abi json description of the contract, which is being created\n * @returns contract object\n */\nvar contract = function (abi) {\n\n // return prototype\n return Contract.bind(null, abi);\n};\n\nvar Contract = function (abi, options) {\n\n this.address = '';\n if (utils.isAddress(options)) {\n this.address = options;\n } else { // is an object!\n // TODO, parse the rest of the args\n options = options || {};\n var args = Array.prototype.slice.call(arguments, 2);\n var bytes = solAbi.formatConstructorParams(abi, args);\n options.data += bytes;\n this.address = web3.eth.sendTransaction(options);\n }\n\n addFunctionsToContract(this, abi);\n addEventsToContract(this, abi);\n};\n\nContract.prototype.call = function () {\n console.error('contract.call is deprecated');\n return this;\n};\n\nContract.prototype.sendTransaction = function () {\n console.error('contract.sendTransact is deprecated');\n return this;\n};\n\nmodule.exports = contract;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file db.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar Method = require('./method');\n\nvar putString = new Method({\n name: 'putString',\n call: 'db_putString',\n params: 3\n});\n\n\nvar getString = new Method({\n name: 'getString',\n call: 'db_getString',\n params: 2\n});\n\nvar putHex = new Method({\n name: 'putHex',\n call: 'db_putHex',\n params: 3\n});\n\nvar getHex = new Method({\n name: 'getHex',\n call: 'db_getHex',\n params: 2\n});\n\nvar methods = [\n putString, getString, putHex, getHex\n];\n\nmodule.exports = {\n methods: methods\n};\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file errors.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nmodule.exports = {\n InvalidNumberOfParams: function () {\n return new Error('Invalid number of input parameters');\n },\n InvalidConnection: function (host){\n return new Error('CONNECTION ERROR: Couldn\\'t connect to node '+ host +', is it running?');\n },\n InvalidProvider: function () {\n return new Error('Providor not set or invalid');\n },\n InvalidResponse: function (result){\n var message = !!result && !!result.error && !!result.error.message ? result.error.message : 'Invalid JSON RPC response';\n return new Error(message);\n }\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/**\n * @file eth.js\n * @author Marek Kotewicz \n * @author Fabian Vogelsteller \n * @date 2015\n */\n\n/**\n * Web3\n * \n * @module web3\n */\n\n/**\n * Eth methods and properties\n *\n * An example method object can look as follows:\n *\n * {\n * name: 'getBlock',\n * call: blockCall,\n * params: 2,\n * outputFormatter: formatters.outputBlockFormatter,\n * inputFormatter: [ // can be a formatter funciton or an array of functions. Where each item in the array will be used for one parameter\n * utils.toHex, // formats paramter 1\n * function(param){ return !!param; } // formats paramter 2\n * ]\n * },\n *\n * @class [web3] eth\n * @constructor\n */\n\n\"use strict\";\n\nvar formatters = require('./formatters');\nvar utils = require('../utils/utils');\nvar Method = require('./method');\nvar Property = require('./property');\n\nvar blockCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? \"eth_getBlockByHash\" : \"eth_getBlockByNumber\";\n};\n\nvar transactionFromBlockCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getTransactionByBlockHashAndIndex' : 'eth_getTransactionByBlockNumberAndIndex';\n};\n\nvar uncleCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getUncleByBlockHashAndIndex' : 'eth_getUncleByBlockNumberAndIndex';\n};\n\nvar getBlockTransactionCountCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getBlockTransactionCountByHash' : 'eth_getBlockTransactionCountByNumber';\n};\n\nvar uncleCountCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getUncleCountByBlockHash' : 'eth_getUncleCountByBlockNumber';\n};\n\n/// @returns an array of objects describing web3.eth api methods\n\nvar getBalance = new Method({\n name: 'getBalance', \n call: 'eth_getBalance', \n params: 2,\n inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter],\n outputFormatter: formatters.outputBigNumberFormatter\n});\n\nvar getStorageAt = new Method({\n name: 'getStorageAt', \n call: 'eth_getStorageAt', \n params: 3,\n inputFormatter: [null, utils.toHex, formatters.inputDefaultBlockNumberFormatter]\n});\n\nvar getCode = new Method({\n name: 'getCode',\n call: 'eth_getCode',\n params: 2,\n inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter]\n});\n\nvar getBlock = new Method({\n name: 'getBlock', \n call: blockCall,\n params: 2,\n inputFormatter: [formatters.inputBlockNumberFormatter, function (val) { return !!val; }],\n outputFormatter: formatters.outputBlockFormatter\n});\n\nvar getUncle = new Method({\n name: 'getUncle',\n call: uncleCall,\n params: 2,\n inputFormatter: [formatters.inputBlockNumberFormatter, utils.toHex],\n outputFormatter: formatters.outputBlockFormatter,\n\n});\n\nvar getCompilers = new Method({\n name: 'getCompilers',\n call: 'eth_getCompilers',\n params: 0\n});\n\nvar getBlockTransactionCount = new Method({\n name: 'getBlockTransactionCount',\n call: getBlockTransactionCountCall,\n params: 1,\n inputFormatter: [formatters.inputBlockNumberFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar getBlockUncleCount = new Method({\n name: 'getBlockUncleCount',\n call: uncleCountCall,\n params: 1,\n inputFormatter: [formatters.inputBlockNumberFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar getTransaction = new Method({\n name: 'getTransaction',\n call: 'eth_getTransactionByHash',\n params: 1,\n outputFormatter: formatters.outputTransactionFormatter\n});\n\nvar getTransactionFromBlock = new Method({\n name: 'getTransactionFromBlock',\n call: transactionFromBlockCall,\n params: 2,\n inputFormatter: [formatters.inputBlockNumberFormatter, utils.toHex],\n outputFormatter: formatters.outputTransactionFormatter\n});\n\nvar getTransactionCount = new Method({\n name: 'getTransactionCount',\n call: 'eth_getTransactionCount',\n params: 2,\n inputFormatter: [null, formatters.inputDefaultBlockNumberFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar sendTransaction = new Method({\n name: 'sendTransaction',\n call: 'eth_sendTransaction',\n params: 1,\n inputFormatter: [formatters.inputTransactionFormatter]\n});\n\nvar call = new Method({\n name: 'call',\n call: 'eth_call',\n params: 2,\n inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter]\n});\n\nvar compileSolidity = new Method({\n name: 'compile.solidity',\n call: 'eth_compileSolidity',\n params: 1\n});\n\nvar compileLLL = new Method({\n name: 'compile.lll',\n call: 'eth_compileLLL',\n params: 1\n});\n\nvar compileSerpent = new Method({\n name: 'compile.serpent',\n call: 'eth_compileSerpent',\n params: 1\n});\n\nvar methods = [\n getBalance,\n getStorageAt,\n getCode,\n getBlock,\n getUncle,\n getCompilers,\n getBlockTransactionCount,\n getBlockUncleCount,\n getTransaction,\n getTransactionFromBlock,\n getTransactionCount,\n call,\n sendTransaction,\n compileSolidity,\n compileLLL,\n compileSerpent,\n];\n\n/// @returns an array of objects describing web3.eth api properties\n\n\n\nvar properties = [\n new Property({\n name: 'coinbase',\n getter: 'eth_coinbase'\n }),\n new Property({\n name: 'mining',\n getter: 'eth_mining'\n }),\n new Property({\n name: 'gasPrice',\n getter: 'eth_gasPrice',\n outputFormatter: formatters.outputBigNumberFormatter\n }),\n new Property({\n name: 'accounts',\n getter: 'eth_accounts'\n }),\n new Property({\n name: 'blockNumber',\n getter: 'eth_blockNumber',\n outputFormatter: utils.toDecimal\n })\n];\n\nmodule.exports = {\n methods: methods,\n properties: properties\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file event.js\n * @author Marek Kotewicz \n * @date 2014\n */\n\nvar utils = require('../utils/utils');\nvar coder = require('../solidity/coder');\nvar web3 = require('../web3');\nvar formatters = require('./formatters');\n\n/**\n * This prototype should be used to create event filters\n */\nvar SolidityEvent = function (json, address) {\n this._params = json.inputs;\n this._name = utils.transformToFullName(json);\n this._address = address;\n this._anonymous = json.anonymous;\n};\n\n/**\n * Should be used to get filtered param types\n *\n * @method types\n * @param {Bool} decide if returned typed should be indexed\n * @return {Array} array of types\n */\nSolidityEvent.prototype.types = function (indexed) {\n return this._params.filter(function (i) {\n return i.indexed === indexed;\n }).map(function (i) {\n return i.type;\n });\n};\n\n/**\n * Should be used to get event display name\n *\n * @method displayName\n * @return {String} event display name\n */\nSolidityEvent.prototype.displayName = function () {\n return utils.extractDisplayName(this._name);\n};\n\n/**\n * Should be used to get event type name\n *\n * @method typeName\n * @return {String} event type name\n */\nSolidityEvent.prototype.typeName = function () {\n return utils.extractTypeName(this._name);\n};\n\n/**\n * Should be used to get event signature\n *\n * @method signature\n * @return {String} event signature\n */\nSolidityEvent.prototype.signature = function () {\n return web3.sha3(web3.fromAscii(this._name)).slice(2);\n};\n\n/**\n * Should be used to encode indexed params and options to one final object\n * \n * @method encode\n * @param {Object} indexed\n * @param {Object} options\n * @return {Object} everything combined together and encoded\n */\nSolidityEvent.prototype.encode = function (indexed, options) {\n indexed = indexed || {};\n options = options || {};\n var result = {};\n\n ['fromBlock', 'toBlock'].filter(function (f) {\n return options[f] !== undefined;\n }).forEach(function (f) {\n result[f] = utils.toHex(options[f]);\n });\n\n result.topics = [];\n\n if (!this._anonymous) {\n result.address = this._address;\n result.topics.push('0x' + this.signature());\n }\n\n var indexedTopics = this._params.filter(function (i) {\n return i.indexed === true;\n }).map(function (i) {\n var value = indexed[i.name];\n if (value === undefined || value === null) {\n return null;\n }\n \n if (utils.isArray(value)) {\n return value.map(function (v) {\n return '0x' + coder.encodeParam(i.type, v);\n });\n }\n return '0x' + coder.encodeParam(i.type, value);\n });\n\n result.topics = result.topics.concat(indexedTopics);\n\n return result;\n};\n\n/**\n * Should be used to decode indexed params and options\n *\n * @method decode\n * @param {Object} data\n * @return {Object} result object with decoded indexed && not indexed params\n */\nSolidityEvent.prototype.decode = function (data) {\n \n data.data = data.data || '';\n data.topics = data.topics || [];\n\n var argTopics = this._anonymous ? data.topics : data.topics.slice(1);\n var indexedData = argTopics.map(function (topics) { return topics.slice(2); }).join(\"\");\n var indexedParams = coder.decodeParams(this.types(true), indexedData); \n\n var notIndexedData = data.data.slice(2);\n var notIndexedParams = coder.decodeParams(this.types(false), notIndexedData);\n \n var result = formatters.outputLogFormatter(data);\n result.event = this.displayName();\n result.address = data.address;\n\n result.args = this._params.reduce(function (acc, current) {\n acc[current.name] = current.indexed ? indexedParams.shift() : notIndexedParams.shift();\n return acc;\n }, {});\n\n delete result.data;\n delete result.topics;\n\n return result;\n};\n\n/**\n * Should be used to create new filter object from event\n *\n * @method execute\n * @param {Object} indexed\n * @param {Object} options\n * @return {Object} filter object\n */\nSolidityEvent.prototype.execute = function (indexed, options) {\n var o = this.encode(indexed, options);\n var formatter = this.decode.bind(this);\n return web3.eth.filter(o, undefined, undefined, formatter);\n};\n\n/**\n * Should be used to attach event to contract object\n *\n * @method attachToContract\n * @param {Contract}\n */\nSolidityEvent.prototype.attachToContract = function (contract) {\n var execute = this.execute.bind(this);\n var displayName = this.displayName();\n if (!contract[displayName]) {\n contract[displayName] = execute;\n }\n contract[displayName][this.typeName()] = this.execute.bind(this, contract);\n};\n\nmodule.exports = SolidityEvent;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/**\n * @file eth.js\n * @author Marek Kotewicz \n * @author Fabian Vogelsteller \n * @date 2015\n */\n\n/**\n * Web3\n *\n * @module web3\n */\n\n/**\n * Eth methods and properties\n *\n * An example method object can look as follows:\n *\n * {\n * name: 'getBlock',\n * call: blockCall,\n * params: 2,\n * outputFormatter: formatters.outputBlockFormatter,\n * inputFormatter: [ // can be a formatter funciton or an array of functions. Where each item in the array will be used for one parameter\n * utils.toHex, // formats paramter 1\n * function(param){ return !!param; } // formats paramter 2\n * ]\n * },\n *\n * @class [web3] eth\n * @constructor\n */\n\n\"use strict\";\n\nvar formatters = require('./formatters');\nvar utils = require('../utils/utils');\nvar Method = require('./method');\nvar Property = require('./property');\n\nvar blockCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? \"eth_getBlockByHash\" : \"eth_getBlockByNumber\";\n};\n\nvar transactionFromBlockCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getTransactionByBlockHashAndIndex' : 'eth_getTransactionByBlockNumberAndIndex';\n};\n\nvar uncleCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getUncleByBlockHashAndIndex' : 'eth_getUncleByBlockNumberAndIndex';\n};\n\nvar getBlockTransactionCountCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getBlockTransactionCountByHash' : 'eth_getBlockTransactionCountByNumber';\n};\n\nvar uncleCountCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getUncleCountByBlockHash' : 'eth_getUncleCountByBlockNumber';\n};\n\n/// @returns an array of objects describing web3.eth api methods\n\nvar getBalance = new Method({\n name: 'getBalance',\n call: 'eth_getBalance',\n params: 2,\n inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter],\n outputFormatter: formatters.outputBigNumberFormatter\n});\n\nvar getStorageAt = new Method({\n name: 'getStorageAt',\n call: 'eth_getStorageAt',\n params: 3,\n inputFormatter: [null, utils.toHex, formatters.inputDefaultBlockNumberFormatter]\n});\n\nvar getCode = new Method({\n name: 'getCode',\n call: 'eth_getCode',\n params: 2,\n inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter]\n});\n\nvar getBlock = new Method({\n name: 'getBlock',\n call: blockCall,\n params: 2,\n inputFormatter: [formatters.inputBlockNumberFormatter, function (val) { return !!val; }],\n outputFormatter: formatters.outputBlockFormatter\n});\n\nvar getUncle = new Method({\n name: 'getUncle',\n call: uncleCall,\n params: 2,\n inputFormatter: [formatters.inputBlockNumberFormatter, utils.toHex],\n outputFormatter: formatters.outputBlockFormatter,\n\n});\n\nvar getCompilers = new Method({\n name: 'getCompilers',\n call: 'eth_getCompilers',\n params: 0\n});\n\nvar getBlockTransactionCount = new Method({\n name: 'getBlockTransactionCount',\n call: getBlockTransactionCountCall,\n params: 1,\n inputFormatter: [formatters.inputBlockNumberFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar getBlockUncleCount = new Method({\n name: 'getBlockUncleCount',\n call: uncleCountCall,\n params: 1,\n inputFormatter: [formatters.inputBlockNumberFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar getTransaction = new Method({\n name: 'getTransaction',\n call: 'eth_getTransactionByHash',\n params: 1,\n outputFormatter: formatters.outputTransactionFormatter\n});\n\nvar getTransactionFromBlock = new Method({\n name: 'getTransactionFromBlock',\n call: transactionFromBlockCall,\n params: 2,\n inputFormatter: [formatters.inputBlockNumberFormatter, utils.toHex],\n outputFormatter: formatters.outputTransactionFormatter\n});\n\nvar getTransactionCount = new Method({\n name: 'getTransactionCount',\n call: 'eth_getTransactionCount',\n params: 2,\n inputFormatter: [null, formatters.inputDefaultBlockNumberFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar sendTransaction = new Method({\n name: 'sendTransaction',\n call: 'eth_sendTransaction',\n params: 1,\n inputFormatter: [formatters.inputTransactionFormatter]\n});\n\nvar call = new Method({\n name: 'call',\n call: 'eth_call',\n params: 2,\n inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter]\n});\n\nvar compileSolidity = new Method({\n name: 'compile.solidity',\n call: 'eth_compileSolidity',\n params: 1\n});\n\nvar compileLLL = new Method({\n name: 'compile.lll',\n call: 'eth_compileLLL',\n params: 1\n});\n\nvar compileSerpent = new Method({\n name: 'compile.serpent',\n call: 'eth_compileSerpent',\n params: 1\n});\n\nvar methods = [\n getBalance,\n getStorageAt,\n getCode,\n getBlock,\n getUncle,\n getCompilers,\n getBlockTransactionCount,\n getBlockUncleCount,\n getTransaction,\n getTransactionFromBlock,\n getTransactionCount,\n call,\n sendTransaction,\n compileSolidity,\n compileLLL,\n compileSerpent,\n];\n\n/// @returns an array of objects describing web3.eth api properties\n\n\n\nvar properties = [\n new Property({\n name: 'coinbase',\n getter: 'eth_coinbase'\n }),\n new Property({\n name: 'mining',\n getter: 'eth_mining'\n }),\n new Property({\n name: 'hashrate',\n getter: 'eth_hashrate',\n outputFormatter: utils.toDecimal\n }),\n new Property({\n name: 'gasPrice',\n getter: 'eth_gasPrice',\n outputFormatter: formatters.outputBigNumberFormatter\n }),\n new Property({\n name: 'accounts',\n getter: 'eth_accounts'\n }),\n new Property({\n name: 'blockNumber',\n getter: 'eth_blockNumber',\n outputFormatter: utils.toDecimal\n })\n];\n\nmodule.exports = {\n methods: methods,\n properties: properties\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file event.js\n * @author Marek Kotewicz \n * @date 2014\n */\n\nvar utils = require('../utils/utils');\nvar coder = require('../solidity/coder');\nvar web3 = require('../web3');\nvar formatters = require('./formatters');\n\n/**\n * This prototype should be used to create event filters\n */\nvar SolidityEvent = function (json, address) {\n this._params = json.inputs;\n this._name = utils.transformToFullName(json);\n this._address = address;\n this._anonymous = json.anonymous;\n};\n\n/**\n * Should be used to get filtered param types\n *\n * @method types\n * @param {Bool} decide if returned typed should be indexed\n * @return {Array} array of types\n */\nSolidityEvent.prototype.types = function (indexed) {\n return this._params.filter(function (i) {\n return i.indexed === indexed;\n }).map(function (i) {\n return i.type;\n });\n};\n\n/**\n * Should be used to get event display name\n *\n * @method displayName\n * @return {String} event display name\n */\nSolidityEvent.prototype.displayName = function () {\n return utils.extractDisplayName(this._name);\n};\n\n/**\n * Should be used to get event type name\n *\n * @method typeName\n * @return {String} event type name\n */\nSolidityEvent.prototype.typeName = function () {\n return utils.extractTypeName(this._name);\n};\n\n/**\n * Should be used to get event signature\n *\n * @method signature\n * @return {String} event signature\n */\nSolidityEvent.prototype.signature = function () {\n return web3.sha3(web3.fromAscii(this._name)).slice(2);\n};\n\n/**\n * Should be used to encode indexed params and options to one final object\n * \n * @method encode\n * @param {Object} indexed\n * @param {Object} options\n * @return {Object} everything combined together and encoded\n */\nSolidityEvent.prototype.encode = function (indexed, options) {\n indexed = indexed || {};\n options = options || {};\n var result = {};\n\n ['fromBlock', 'toBlock'].filter(function (f) {\n return options[f] !== undefined;\n }).forEach(function (f) {\n result[f] = formatters.inputBlockNumberFormatter(options[f]);\n });\n\n result.topics = [];\n\n if (!this._anonymous) {\n result.address = this._address;\n result.topics.push('0x' + this.signature());\n }\n\n var indexedTopics = this._params.filter(function (i) {\n return i.indexed === true;\n }).map(function (i) {\n var value = indexed[i.name];\n if (value === undefined || value === null) {\n return null;\n }\n \n if (utils.isArray(value)) {\n return value.map(function (v) {\n return '0x' + coder.encodeParam(i.type, v);\n });\n }\n return '0x' + coder.encodeParam(i.type, value);\n });\n\n result.topics = result.topics.concat(indexedTopics);\n\n return result;\n};\n\n/**\n * Should be used to decode indexed params and options\n *\n * @method decode\n * @param {Object} data\n * @return {Object} result object with decoded indexed && not indexed params\n */\nSolidityEvent.prototype.decode = function (data) {\n \n data.data = data.data || '';\n data.topics = data.topics || [];\n\n var argTopics = this._anonymous ? data.topics : data.topics.slice(1);\n var indexedData = argTopics.map(function (topics) { return topics.slice(2); }).join(\"\");\n var indexedParams = coder.decodeParams(this.types(true), indexedData); \n\n var notIndexedData = data.data.slice(2);\n var notIndexedParams = coder.decodeParams(this.types(false), notIndexedData);\n \n var result = formatters.outputLogFormatter(data);\n result.event = this.displayName();\n result.address = data.address;\n\n result.args = this._params.reduce(function (acc, current) {\n acc[current.name] = current.indexed ? indexedParams.shift() : notIndexedParams.shift();\n return acc;\n }, {});\n\n delete result.data;\n delete result.topics;\n\n return result;\n};\n\n/**\n * Should be used to create new filter object from event\n *\n * @method execute\n * @param {Object} indexed\n * @param {Object} options\n * @return {Object} filter object\n */\nSolidityEvent.prototype.execute = function (indexed, options) {\n var o = this.encode(indexed, options);\n var formatter = this.decode.bind(this);\n return web3.eth.filter(o, undefined, undefined, formatter);\n};\n\n/**\n * Should be used to attach event to contract object\n *\n * @method attachToContract\n * @param {Contract}\n */\nSolidityEvent.prototype.attachToContract = function (contract) {\n var execute = this.execute.bind(this);\n var displayName = this.displayName();\n if (!contract[displayName]) {\n contract[displayName] = execute;\n }\n contract[displayName][this.typeName()] = this.execute.bind(this, contract);\n};\n\nmodule.exports = SolidityEvent;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file filter.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * Gav Wood \n * @date 2014\n */\n\nvar RequestManager = require('./requestmanager');\nvar formatters = require('./formatters');\nvar utils = require('../utils/utils');\n\n/**\n* Converts a given topic to a hex string, but also allows null values.\n*\n* @param {Mixed} value\n* @return {String}\n*/\nvar toTopic = function(value){\n\n if(value === null || typeof value === 'undefined')\n return null;\n\n value = String(value);\n\n if(value.indexOf('0x') === 0)\n return value;\n else\n return utils.fromAscii(value);\n};\n\n/// This method should be called on options object, to verify deprecated properties && lazy load dynamic ones\n/// @param should be string or object\n/// @returns options string or object\nvar getOptions = function (options) {\n\n if (utils.isString(options)) {\n return options;\n } \n\n options = options || {};\n\n // make sure topics, get converted to hex\n options.topics = options.topics || [];\n options.topics = options.topics.map(function(topic){\n return (utils.isArray(topic)) ? topic.map(toTopic) : toTopic(topic);\n });\n\n // lazy load\n return {\n topics: options.topics,\n to: options.to,\n address: options.address,\n fromBlock: formatters.inputBlockNumberFormatter(options.fromBlock),\n toBlock: formatters.inputBlockNumberFormatter(options.toBlock) \n }; \n};\n\nvar Filter = function (options, methods, formatter) {\n var implementation = {};\n methods.forEach(function (method) {\n method.attachToObject(implementation);\n });\n this.options = getOptions(options);\n this.implementation = implementation;\n this.callbacks = [];\n this.formatter = formatter;\n this.filterId = this.implementation.newFilter(this.options);\n};\n\nFilter.prototype.watch = function (callback) {\n this.callbacks.push(callback);\n var self = this;\n\n var onMessage = function (error, messages) {\n if (error) {\n return self.callbacks.forEach(function (callback) {\n callback(error);\n });\n }\n\n messages.forEach(function (message) {\n message = self.formatter ? self.formatter(message) : message;\n self.callbacks.forEach(function (callback) {\n callback(null, message);\n });\n });\n };\n\n // call getFilterLogs on start\n if (!utils.isString(this.options)) {\n this.get(function (err, messages) {\n // don't send all the responses to all the watches again... just to this one\n if (err) {\n callback(err);\n }\n\n messages.forEach(function (message) {\n callback(null, message);\n });\n });\n }\n\n RequestManager.getInstance().startPolling({\n method: this.implementation.poll.call,\n params: [this.filterId],\n }, this.filterId, onMessage, this.stopWatching.bind(this));\n};\n\nFilter.prototype.stopWatching = function () {\n RequestManager.getInstance().stopPolling(this.filterId);\n this.implementation.uninstallFilter(this.filterId);\n this.callbacks = [];\n};\n\nFilter.prototype.get = function (callback) {\n var self = this;\n if (utils.isFunction(callback)) {\n this.implementation.getLogs(this.filterId, function(err, res){\n if (err) {\n callback(err);\n } else {\n callback(null, res.map(function (log) {\n return self.formatter ? self.formatter(log) : log;\n }));\n }\n });\n } else {\n var logs = this.implementation.getLogs(this.filterId);\n return logs.map(function (log) {\n return self.formatter ? self.formatter(log) : log;\n });\n }\n};\n\nmodule.exports = Filter;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file formatters.js\n * @author Marek Kotewicz \n * @author Fabian Vogelsteller \n * @date 2015\n */\n\nvar utils = require('../utils/utils');\nvar config = require('../utils/config');\n\n/**\n * Should the format output to a big number\n *\n * @method outputBigNumberFormatter\n * @param {String|Number|BigNumber}\n * @returns {BigNumber} object\n */\nvar outputBigNumberFormatter = function (number) {\n return utils.toBigNumber(number);\n};\n\nvar isPredefinedBlockNumber = function (blockNumber) {\n return blockNumber === 'latest' || blockNumber === 'pending' || blockNumber === 'earliest';\n};\n\nvar inputDefaultBlockNumberFormatter = function (blockNumber) {\n if (blockNumber === undefined) {\n return config.defaultBlock;\n }\n return inputBlockNumberFormatter(blockNumber);\n};\n\nvar inputBlockNumberFormatter = function (blockNumber) {\n if (blockNumber === undefined) {\n return undefined;\n } else if (isPredefinedBlockNumber(blockNumber)) {\n return blockNumber;\n }\n return utils.toHex(blockNumber);\n};\n\n/**\n * Formats the input of a transaction and converts all values to HEX\n *\n * @method inputTransactionFormatter\n * @param {Object} transaction options\n * @returns object\n*/\nvar inputTransactionFormatter = function (options){\n\n options.from = options.from || config.defaultAccount;\n\n // make code -> data\n if (options.code) {\n options.data = options.code;\n delete options.code;\n }\n\n ['gasPrice', 'gas', 'value'].filter(function (key) {\n return options[key] !== undefined;\n }).forEach(function(key){\n options[key] = utils.fromDecimal(options[key]);\n });\n\n return options; \n};\n\n/**\n * Formats the output of a transaction to its proper values\n * \n * @method outputTransactionFormatter\n * @param {Object} transaction\n * @returns {Object} transaction\n*/\nvar outputTransactionFormatter = function (tx){\n tx.blockNumber = utils.toDecimal(tx.blockNumber);\n tx.transactionIndex = utils.toDecimal(tx.transactionIndex);\n tx.nonce = utils.toDecimal(tx.nonce);\n tx.gas = utils.toDecimal(tx.gas);\n tx.gasPrice = utils.toBigNumber(tx.gasPrice);\n tx.value = utils.toBigNumber(tx.value);\n return tx;\n};\n\n/**\n * Formats the output of a block to its proper values\n *\n * @method outputBlockFormatter\n * @param {Object} block object \n * @returns {Object} block object\n*/\nvar outputBlockFormatter = function(block) {\n\n // transform to number\n block.gasLimit = utils.toDecimal(block.gasLimit);\n block.gasUsed = utils.toDecimal(block.gasUsed);\n block.size = utils.toDecimal(block.size);\n block.timestamp = utils.toDecimal(block.timestamp);\n block.number = utils.toDecimal(block.number);\n\n block.difficulty = utils.toBigNumber(block.difficulty);\n block.totalDifficulty = utils.toBigNumber(block.totalDifficulty);\n\n if (utils.isArray(block.transactions)) {\n block.transactions.forEach(function(item){\n if(!utils.isString(item))\n return outputTransactionFormatter(item);\n });\n }\n\n return block;\n};\n\n/**\n * Formats the output of a log\n * \n * @method outputLogFormatter\n * @param {Object} log object\n * @returns {Object} log\n*/\nvar outputLogFormatter = function(log) {\n if (log === null) { // 'pending' && 'latest' filters are nulls\n return null;\n }\n\n log.blockNumber = utils.toDecimal(log.blockNumber);\n log.transactionIndex = utils.toDecimal(log.transactionIndex);\n log.logIndex = utils.toDecimal(log.logIndex);\n\n return log;\n};\n\n/**\n * Formats the input of a whisper post and converts all values to HEX\n *\n * @method inputPostFormatter\n * @param {Object} transaction object\n * @returns {Object}\n*/\nvar inputPostFormatter = function(post) {\n\n post.payload = utils.toHex(post.payload);\n post.ttl = utils.fromDecimal(post.ttl);\n post.workToProve = utils.fromDecimal(post.workToProve);\n post.priority = utils.fromDecimal(post.priority);\n\n // fallback\n if (!utils.isArray(post.topics)) {\n post.topics = post.topics ? [post.topics] : [];\n }\n\n // format the following options\n post.topics = post.topics.map(function(topic){\n return utils.fromAscii(topic);\n });\n\n return post; \n};\n\n/**\n * Formats the output of a received post message\n *\n * @method outputPostFormatter\n * @param {Object}\n * @returns {Object}\n */\nvar outputPostFormatter = function(post){\n\n post.expiry = utils.toDecimal(post.expiry);\n post.sent = utils.toDecimal(post.sent);\n post.ttl = utils.toDecimal(post.ttl);\n post.workProved = utils.toDecimal(post.workProved);\n post.payloadRaw = post.payload;\n post.payload = utils.toAscii(post.payload);\n\n if (utils.isJson(post.payload)) {\n post.payload = JSON.parse(post.payload);\n }\n\n // format the following options\n if (!post.topics) {\n post.topics = [];\n }\n post.topics = post.topics.map(function(topic){\n return utils.toAscii(topic);\n });\n\n return post;\n};\n\nmodule.exports = {\n inputDefaultBlockNumberFormatter: inputDefaultBlockNumberFormatter,\n inputBlockNumberFormatter: inputBlockNumberFormatter,\n inputTransactionFormatter: inputTransactionFormatter,\n inputPostFormatter: inputPostFormatter,\n outputBigNumberFormatter: outputBigNumberFormatter,\n outputTransactionFormatter: outputTransactionFormatter,\n outputBlockFormatter: outputBlockFormatter,\n outputLogFormatter: outputLogFormatter,\n outputPostFormatter: outputPostFormatter\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file formatters.js\n * @author Marek Kotewicz \n * @author Fabian Vogelsteller \n * @date 2015\n */\n\nvar utils = require('../utils/utils');\nvar config = require('../utils/config');\n\n/**\n * Should the format output to a big number\n *\n * @method outputBigNumberFormatter\n * @param {String|Number|BigNumber}\n * @returns {BigNumber} object\n */\nvar outputBigNumberFormatter = function (number) {\n return utils.toBigNumber(number);\n};\n\nvar isPredefinedBlockNumber = function (blockNumber) {\n return blockNumber === 'latest' || blockNumber === 'pending' || blockNumber === 'earliest';\n};\n\nvar inputDefaultBlockNumberFormatter = function (blockNumber) {\n if (blockNumber === undefined) {\n return config.defaultBlock;\n }\n return inputBlockNumberFormatter(blockNumber);\n};\n\nvar inputBlockNumberFormatter = function (blockNumber) {\n if (blockNumber === undefined) {\n return undefined;\n } else if (isPredefinedBlockNumber(blockNumber)) {\n return blockNumber;\n }\n return utils.toHex(blockNumber);\n};\n\n/**\n * Formats the input of a transaction and converts all values to HEX\n *\n * @method inputTransactionFormatter\n * @param {Object} transaction options\n * @returns object\n*/\nvar inputTransactionFormatter = function (options){\n\n options.from = options.from || config.defaultAccount;\n\n // make code -> data\n if (options.code) {\n options.data = options.code;\n delete options.code;\n }\n\n ['gasPrice', 'gas', 'value', 'nonce'].filter(function (key) {\n return options[key] !== undefined;\n }).forEach(function(key){\n options[key] = utils.fromDecimal(options[key]);\n });\n\n return options; \n};\n\n/**\n * Formats the output of a transaction to its proper values\n * \n * @method outputTransactionFormatter\n * @param {Object} transaction\n * @returns {Object} transaction\n*/\nvar outputTransactionFormatter = function (tx){\n tx.blockNumber = utils.toDecimal(tx.blockNumber);\n tx.transactionIndex = utils.toDecimal(tx.transactionIndex);\n tx.nonce = utils.toDecimal(tx.nonce);\n tx.gas = utils.toDecimal(tx.gas);\n tx.gasPrice = utils.toBigNumber(tx.gasPrice);\n tx.value = utils.toBigNumber(tx.value);\n return tx;\n};\n\n/**\n * Formats the output of a block to its proper values\n *\n * @method outputBlockFormatter\n * @param {Object} block object \n * @returns {Object} block object\n*/\nvar outputBlockFormatter = function(block) {\n\n // transform to number\n block.gasLimit = utils.toDecimal(block.gasLimit);\n block.gasUsed = utils.toDecimal(block.gasUsed);\n block.size = utils.toDecimal(block.size);\n block.timestamp = utils.toDecimal(block.timestamp);\n block.number = utils.toDecimal(block.number);\n\n block.difficulty = utils.toBigNumber(block.difficulty);\n block.totalDifficulty = utils.toBigNumber(block.totalDifficulty);\n\n if (utils.isArray(block.transactions)) {\n block.transactions.forEach(function(item){\n if(!utils.isString(item))\n return outputTransactionFormatter(item);\n });\n }\n\n return block;\n};\n\n/**\n * Formats the output of a log\n * \n * @method outputLogFormatter\n * @param {Object} log object\n * @returns {Object} log\n*/\nvar outputLogFormatter = function(log) {\n if (log === null) { // 'pending' && 'latest' filters are nulls\n return null;\n }\n\n log.blockNumber = utils.toDecimal(log.blockNumber);\n log.transactionIndex = utils.toDecimal(log.transactionIndex);\n log.logIndex = utils.toDecimal(log.logIndex);\n\n return log;\n};\n\n/**\n * Formats the input of a whisper post and converts all values to HEX\n *\n * @method inputPostFormatter\n * @param {Object} transaction object\n * @returns {Object}\n*/\nvar inputPostFormatter = function(post) {\n\n post.payload = utils.toHex(post.payload);\n post.ttl = utils.fromDecimal(post.ttl);\n post.workToProve = utils.fromDecimal(post.workToProve);\n post.priority = utils.fromDecimal(post.priority);\n\n // fallback\n if (!utils.isArray(post.topics)) {\n post.topics = post.topics ? [post.topics] : [];\n }\n\n // format the following options\n post.topics = post.topics.map(function(topic){\n return utils.fromAscii(topic);\n });\n\n return post; \n};\n\n/**\n * Formats the output of a received post message\n *\n * @method outputPostFormatter\n * @param {Object}\n * @returns {Object}\n */\nvar outputPostFormatter = function(post){\n\n post.expiry = utils.toDecimal(post.expiry);\n post.sent = utils.toDecimal(post.sent);\n post.ttl = utils.toDecimal(post.ttl);\n post.workProved = utils.toDecimal(post.workProved);\n post.payloadRaw = post.payload;\n post.payload = utils.toAscii(post.payload);\n\n if (utils.isJson(post.payload)) {\n post.payload = JSON.parse(post.payload);\n }\n\n // format the following options\n if (!post.topics) {\n post.topics = [];\n }\n post.topics = post.topics.map(function(topic){\n return utils.toAscii(topic);\n });\n\n return post;\n};\n\nmodule.exports = {\n inputDefaultBlockNumberFormatter: inputDefaultBlockNumberFormatter,\n inputBlockNumberFormatter: inputBlockNumberFormatter,\n inputTransactionFormatter: inputTransactionFormatter,\n inputPostFormatter: inputPostFormatter,\n outputBigNumberFormatter: outputBigNumberFormatter,\n outputTransactionFormatter: outputTransactionFormatter,\n outputBlockFormatter: outputBlockFormatter,\n outputLogFormatter: outputLogFormatter,\n outputPostFormatter: outputPostFormatter\n};\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file function.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar web3 = require('../web3');\nvar coder = require('../solidity/coder');\nvar utils = require('../utils/utils');\n\n/**\n * This prototype should be used to call/sendTransaction to solidity functions\n */\nvar SolidityFunction = function (json, address) {\n this._inputTypes = json.inputs.map(function (i) {\n return i.type;\n });\n this._outputTypes = json.outputs.map(function (i) {\n return i.type;\n });\n this._constant = json.constant;\n this._name = utils.transformToFullName(json);\n this._address = address;\n};\n\n/**\n * Should be used to create payload from arguments\n *\n * @method toPayload\n * @param {...} solidity function params\n * @param {Object} optional payload options\n */\nSolidityFunction.prototype.toPayload = function () {\n var args = Array.prototype.slice.call(arguments);\n var options = {};\n if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) {\n options = args.pop();\n }\n options.to = this._address;\n options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args);\n return options;\n};\n\n/**\n * Should be used to get function signature\n *\n * @method signature\n * @return {String} function signature\n */\nSolidityFunction.prototype.signature = function () {\n return web3.sha3(web3.fromAscii(this._name)).slice(2, 10);\n};\n\n/**\n * Should be used to call function\n * \n * @method call\n * @param {Object} options\n * @return {String} output bytes\n */\nSolidityFunction.prototype.call = function () {\n var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments));\n var output = web3.eth.call(payload);\n output = output.length >= 2 ? output.slice(2) : output;\n var result = coder.decodeParams(this._outputTypes, output);\n return result.length === 1 ? result[0] : result;\n};\n\n/**\n * Should be used to sendTransaction to solidity function\n *\n * @method sendTransaction\n * @param {Object} options\n */\nSolidityFunction.prototype.sendTransaction = function () {\n var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments));\n web3.eth.sendTransaction(payload);\n};\n\n/**\n * Should be used to get function display name\n *\n * @method displayName\n * @return {String} display name of the function\n */\nSolidityFunction.prototype.displayName = function () {\n return utils.extractDisplayName(this._name);\n};\n\n/**\n * Should be used to get function type name\n * \n * @method typeName\n * @return {String} type name of the function\n */\nSolidityFunction.prototype.typeName = function () {\n return utils.extractTypeName(this._name);\n};\n\n/**\n * Should be called to execute function\n *\n * @method execute\n */\nSolidityFunction.prototype.execute = function () {\n var transaction = !this._constant;\n \n // send transaction\n if (transaction) {\n return this.sendTransaction.apply(this, Array.prototype.slice.call(arguments));\n }\n\n // call\n return this.call.apply(this, Array.prototype.slice.call(arguments));\n};\n\n/**\n * Should be called to attach function to contract\n *\n * @method attachToContract\n * @param {Contract}\n */\nSolidityFunction.prototype.attachToContract = function (contract) {\n var execute = this.execute.bind(this);\n execute.call = this.call.bind(this);\n execute.sendTransaction = this.sendTransaction.bind(this);\n var displayName = this.displayName();\n if (!contract[displayName]) {\n contract[displayName] = execute;\n }\n contract[displayName][this.typeName()] = execute; // circular!!!!\n};\n\nmodule.exports = SolidityFunction;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file httpprovider.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * @date 2014\n */\n\n\"use strict\";\n\nvar XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\nvar errors = require('./errors');\n\nvar HttpProvider = function (host) {\n this.host = host || 'http://localhost:8545';\n};\n\nHttpProvider.prototype.send = function (payload) {\n var request = new XMLHttpRequest();\n\n request.open('POST', this.host, false);\n \n try {\n request.send(JSON.stringify(payload));\n } catch(error) {\n throw errors.InvalidConnection(this.host);\n }\n\n\n // check request.status\n // TODO: throw an error here! it cannot silently fail!!!\n //if (request.status !== 200) {\n //return;\n //}\n return JSON.parse(request.responseText);\n};\n\nHttpProvider.prototype.sendAsync = function (payload, callback) {\n var request = new XMLHttpRequest();\n request.onreadystatechange = function() {\n if (request.readyState === 4) {\n // TODO: handle the error properly here!!!\n callback(null, JSON.parse(request.responseText));\n }\n };\n\n request.open('POST', this.host, true);\n\n try {\n request.send(JSON.stringify(payload));\n } catch(error) {\n callback(errors.InvalidConnection(this.host));\n }\n};\n\nmodule.exports = HttpProvider;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file httpprovider.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * @date 2014\n */\n\n\"use strict\";\n\nvar XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\nvar errors = require('./errors');\n\nvar HttpProvider = function (host) {\n this.host = host || 'http://localhost:8545';\n};\n\nHttpProvider.prototype.send = function (payload) {\n var request = new XMLHttpRequest();\n\n request.open('POST', this.host, false);\n \n try {\n request.send(JSON.stringify(payload));\n } catch(error) {\n throw errors.InvalidConnection(this.host);\n }\n\n\n // check request.status\n // TODO: throw an error here! it cannot silently fail!!!\n //if (request.status !== 200) {\n //return;\n //}\n\n var result = request.responseText;\n\n try {\n result = JSON.parse(result);\n } catch(e) {\n throw errors.InvalidResponse(result); \n }\n\n return result;\n};\n\nHttpProvider.prototype.sendAsync = function (payload, callback) {\n var request = new XMLHttpRequest();\n request.onreadystatechange = function() {\n if (request.readyState === 4) {\n var result = request.responseText;\n var error = null;\n\n try {\n result = JSON.parse(result);\n } catch(e) {\n error = errors.InvalidResponse(result); \n }\n\n callback(error, result);\n }\n };\n\n request.open('POST', this.host, true);\n\n try {\n request.send(JSON.stringify(payload));\n } catch(error) {\n callback(errors.InvalidConnection(this.host));\n }\n};\n\nmodule.exports = HttpProvider;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file jsonrpc.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar Jsonrpc = function () {\n // singleton pattern\n if (arguments.callee._singletonInstance) {\n return arguments.callee._singletonInstance;\n }\n arguments.callee._singletonInstance = this;\n\n this.messageId = 1;\n};\n\n/**\n * @return {Jsonrpc} singleton\n */\nJsonrpc.getInstance = function () {\n var instance = new Jsonrpc();\n return instance;\n};\n\n/**\n * Should be called to valid json create payload object\n *\n * @method toPayload\n * @param {Function} method of jsonrpc call, required\n * @param {Array} params, an array of method params, optional\n * @returns {Object} valid jsonrpc payload object\n */\nJsonrpc.prototype.toPayload = function (method, params) {\n if (!method)\n console.error('jsonrpc method should be specified!');\n\n return {\n jsonrpc: '2.0',\n method: method,\n params: params || [],\n id: this.messageId++\n };\n};\n\n/**\n * Should be called to check if jsonrpc response is valid\n *\n * @method isValidResponse\n * @param {Object}\n * @returns {Boolean} true if response is valid, otherwise false\n */\nJsonrpc.prototype.isValidResponse = function (response) {\n return !!response &&\n !response.error &&\n response.jsonrpc === '2.0' &&\n typeof response.id === 'number' &&\n response.result !== undefined; // only undefined is not valid json object\n};\n\n/**\n * Should be called to create batch payload object\n *\n * @method toBatchPayload\n * @param {Array} messages, an array of objects with method (required) and params (optional) fields\n * @returns {Array} batch payload\n */\nJsonrpc.prototype.toBatchPayload = function (messages) {\n var self = this;\n return messages.map(function (message) {\n return self.toPayload(message.method, message.params);\n });\n};\n\nmodule.exports = Jsonrpc;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/**\n * @file method.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar RequestManager = require('./requestmanager');\nvar utils = require('../utils/utils');\nvar errors = require('./errors');\n\nvar Method = function (options) {\n this.name = options.name;\n this.call = options.call;\n this.params = options.params || 0;\n this.inputFormatter = options.inputFormatter;\n this.outputFormatter = options.outputFormatter;\n};\n\n/**\n * Should be used to determine name of the jsonrpc method based on arguments\n *\n * @method getCall\n * @param {Array} arguments\n * @return {String} name of jsonrpc method\n */\nMethod.prototype.getCall = function (args) {\n return utils.isFunction(this.call) ? this.call(args) : this.call;\n};\n\n/**\n * Should be used to extract callback from array of arguments. Modifies input param\n *\n * @method extractCallback\n * @param {Array} arguments\n * @return {Function|Null} callback, if exists\n */\nMethod.prototype.extractCallback = function (args) {\n if (utils.isFunction(args[args.length - 1])) {\n return args.pop(); // modify the args array!\n }\n return null;\n};\n\n/**\n * Should be called to check if the number of arguments is correct\n * \n * @method validateArgs\n * @param {Array} arguments\n * @throws {Error} if it is not\n */\nMethod.prototype.validateArgs = function (args) {\n if (args.length !== this.params) {\n throw errors.InvalidNumberOfParams();\n }\n};\n\n/**\n * Should be called to format input args of method\n * \n * @method formatInput\n * @param {Array}\n * @return {Array}\n */\nMethod.prototype.formatInput = function (args) {\n if (!this.inputFormatter) {\n return args;\n }\n\n return this.inputFormatter.map(function (formatter, index) {\n return formatter ? formatter(args[index]) : args[index];\n });\n};\n\n/**\n * Should be called to format output(result) of method\n *\n * @method formatOutput\n * @param {Object}\n * @return {Object}\n */\nMethod.prototype.formatOutput = function (result) {\n return this.outputFormatter && result !== null ? this.outputFormatter(result) : result;\n};\n\n/**\n * Should attach function to method\n * \n * @method attachToObject\n * @param {Object}\n * @param {Function}\n */\nMethod.prototype.attachToObject = function (obj) {\n var func = this.send.bind(this);\n func.call = this.call; // that's ugly. filter.js uses it\n var name = this.name.split('.');\n if (name.length > 1) {\n obj[name[0]] = obj[name[0]] || {};\n obj[name[0]][name[1]] = func;\n } else {\n obj[name[0]] = func; \n }\n};\n\n/**\n * Should create payload from given input args\n *\n * @method toPayload\n * @param {Array} args\n * @return {Object}\n */\nMethod.prototype.toPayload = function (args) {\n var call = this.getCall(args);\n var callback = this.extractCallback(args);\n var params = this.formatInput(args);\n this.validateArgs(params);\n\n return {\n method: call,\n params: params,\n callback: callback\n };\n};\n\n/**\n * Should send request to the API\n *\n * @method send\n * @param list of params\n * @return result\n */\nMethod.prototype.send = function () {\n var payload = this.toPayload(Array.prototype.slice.call(arguments));\n if (payload.callback) {\n var self = this;\n return RequestManager.getInstance().sendAsync(payload, function (err, result) {\n payload.callback(null, self.formatOutput(result));\n });\n }\n return this.formatOutput(RequestManager.getInstance().send(payload));\n};\n\nmodule.exports = Method;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file eth.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar utils = require('../utils/utils');\nvar Property = require('./property');\n\n/// @returns an array of objects describing web3.eth api methods\nvar methods = [\n];\n\n/// @returns an array of objects describing web3.eth api properties\nvar properties = [\n new Property({\n name: 'listening',\n getter: 'net_listening'\n }),\n new Property({\n name: 'peerCount',\n getter: 'net_peerCount',\n outputFormatter: utils.toDecimal\n })\n];\n\n\nmodule.exports = {\n methods: methods,\n properties: properties\n};\n\n", diff --git a/libjsqrc/ethereumjs/dist/web3-light.min.js b/libjsqrc/ethereumjs/dist/web3-light.min.js index e45033791..4c0fd2930 100644 --- a/libjsqrc/ethereumjs/dist/web3-light.min.js +++ b/libjsqrc/ethereumjs/dist/web3-light.min.js @@ -1,2 +1,2 @@ -require=function t(e,r,n){function o(a,s){if(!r[a]){if(!e[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=r[a]={exports:{}};e[a][0].call(l.exports,function(t){var r=e[a][1][t];return o(r?r:t)},l,l.exports,t,e,r,n)}return r[a].exports}for(var i="function"==typeof require&&require,a=0;a0&&console.warn("didn't found matching constructor, using default one"),"")};e.exports={inputParser:u,outputParser:c,formatInput:a,formatOutput:s,formatConstructorParams:l}},{"../utils/utils":8,"./coder":2,"./utils":5}],2:[function(t,e,r){var n=t("bignumber.js"),o=t("../utils/utils"),i=t("./formatters"),a=t("./param"),s=function(t){return"[]"===t.slice(-2)},u=function(t){this._name=t.name,this._match=t.match,this._mode=t.mode,this._inputFormatter=t.inputFormatter,this._outputFormatter=t.outputFormatter};u.prototype.isType=function(t){return"strict"===this._match?this._name===t||0===t.indexOf(this._name)&&"[]"===t.slice(this._name.length):"prefix"===this._match?0===t.indexOf(this._name):void 0},u.prototype.formatInput=function(t,e){if(o.isArray(t)&&e){var r=this;return t.map(function(t){return r._inputFormatter(t)}).reduce(function(t,e){return t.appendArrayElement(e),t},new a("",i.formatInputInt(t.length).value))}return this._inputFormatter(t)},u.prototype.formatOutput=function(t,e){if(e){for(var r=[],o=new n(t.prefix,16),i=0;64*o>i;i+=64)r.push(this._outputFormatter(new a(t.suffix.slice(i,i+64))));return r}return this._outputFormatter(t)},u.prototype.isVariadicType=function(t){return s(t)||"bytes"===this._mode},u.prototype.shiftParam=function(t,e){if("bytes"===this._mode)return e.shiftBytes();if(s(t)){var r=new n(e.prefix.slice(0,64),16);return e.shiftArray(r)}return e.shiftValue()};var c=function(t){this._types=t};c.prototype._requireType=function(t){var e=this._types.filter(function(e){return e.isType(t)})[0];if(!e)throw Error("invalid solidity type!: "+t);return e},c.prototype._bytesToParam=function(t,e){var r=this,n=t.reduce(function(t,e){return r._requireType(e).isVariadicType(e)?t+1:t},0),o=t.length-n,i=e.slice(0,64*n);e=e.slice(64*n);var s=e.slice(0,64*o),u=e.slice(64*o);return new a(s,i,u)},c.prototype._formatInput=function(t,e){return this._requireType(t).formatInput(e,s(t))},c.prototype.encodeParam=function(t,e){return this._formatInput(t,e).encode()},c.prototype.encodeParams=function(t,e){var r=this;return t.map(function(t,n){return r._formatInput(t,e[n])}).reduce(function(t,e){return t.append(e),t},new a).encode()},c.prototype._formatOutput=function(t,e){return this._requireType(t).formatOutput(e,s(t))},c.prototype.decodeParam=function(t,e){return this._formatOutput(t,this._bytesToParam([t],e))},c.prototype.decodeParams=function(t,e){var r=this,n=this._bytesToParam(t,e);return t.map(function(t){var e=r._requireType(t),o=e.shiftParam(t,n);return e.formatOutput(o,s(t))})};var l=new c([new u({name:"address",match:"strict",mode:"value",inputFormatter:i.formatInputInt,outputFormatter:i.formatOutputAddress}),new u({name:"bool",match:"strict",mode:"value",inputFormatter:i.formatInputBool,outputFormatter:i.formatOutputBool}),new u({name:"int",match:"prefix",mode:"value",inputFormatter:i.formatInputInt,outputFormatter:i.formatOutputInt}),new u({name:"uint",match:"prefix",mode:"value",inputFormatter:i.formatInputInt,outputFormatter:i.formatOutputUInt}),new u({name:"bytes",match:"strict",mode:"bytes",inputFormatter:i.formatInputDynamicBytes,outputFormatter:i.formatOutputDynamicBytes}),new u({name:"bytes",match:"prefix",mode:"value",inputFormatter:i.formatInputBytes,outputFormatter:i.formatOutputBytes}),new u({name:"real",match:"prefix",mode:"value",inputFormatter:i.formatInputReal,outputFormatter:i.formatOutputReal}),new u({name:"ureal",match:"prefix",mode:"value",inputFormatter:i.formatInputReal,outputFormatter:i.formatOutputUReal})]);e.exports=l},{"../utils/utils":8,"./formatters":3,"./param":4,"bignumber.js":"bignumber.js"}],3:[function(t,e,r){var n=t("bignumber.js"),o=t("../utils/utils"),i=t("../utils/config"),a=t("./param"),s=function(t){var e=2*i.ETH_PADDING;n.config(i.ETH_BIGNUMBER_ROUNDING_MODE);var r=o.padLeft(o.toTwosComplement(t).round().toString(16),e);return new a(r)},u=function(t){var e=o.fromAscii(t,i.ETH_PADDING).substr(2);return new a(e)},c=function(t){var e=o.fromAscii(t,i.ETH_PADDING).substr(2);return new a("",s(t.length).value,e)},l=function(t){var e="000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0");return new a(e)},p=function(t){return s(new n(t).times(new n(2).pow(128)))},f=function(t){return"1"===new n(t.substr(0,1),16).toString(2).substr(0,1)},m=function(t){var e=t.value||"0";return f(e)?new n(e,16).minus(new n("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new n(e,16)},h=function(t){var e=t.value||"0";return new n(e,16)},d=function(t){return m(t).dividedBy(new n(2).pow(128))},y=function(t){return h(t).dividedBy(new n(2).pow(128))},g=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t.value?!0:!1},v=function(t){return o.toAscii(t.value)},b=function(t){return o.toAscii(t.suffix)},w=function(t){var e=t.value;return"0x"+e.slice(e.length-40,e.length)};e.exports={formatInputInt:s,formatInputBytes:u,formatInputDynamicBytes:c,formatInputBool:l,formatInputReal:p,formatOutputInt:m,formatOutputUInt:h,formatOutputReal:d,formatOutputUReal:y,formatOutputBool:g,formatOutputBytes:v,formatOutputDynamicBytes:b,formatOutputAddress:w}},{"../utils/config":7,"../utils/utils":8,"./param":4,"bignumber.js":"bignumber.js"}],4:[function(t,e,r){var n=function(t,e,r){this.prefix=e||"",this.value=t||"",this.suffix=r||""};n.prototype.append=function(t){this.prefix+=t.prefix,this.value+=t.value,this.suffix+=t.suffix},n.prototype.appendArrayElement=function(t){this.suffix+=t.value,this.prefix+=t.prefix},n.prototype.encode=function(){return this.prefix+this.value+this.suffix},n.prototype.shiftValue=function(){var t=this.value.slice(0,64);return this.value=this.value.slice(64),new n(t)},n.prototype.shiftBytes=function(){return this.shiftArray(1)},n.prototype.shiftArray=function(t){var e=this.prefix.slice(0,64);this.prefix=this.value.slice(64);var r=this.suffix.slice(0,64*t);return this.suffix=this.suffix.slice(64*t),new n("",e,r)},e.exports=n},{}],5:[function(t,e,r){var n=function(t,e){return t.filter(function(t){return"constructor"===t.type&&t.inputs.length===e})[0]};e.exports={getConstructor:n}},{}],6:[function(t,e,r){"use strict";r.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],7:[function(t,e,r){var n=t("bignumber.js"),o=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:o,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:n.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3,defaultBlock:"latest",defaultAccount:void 0}},{"bignumber.js":"bignumber.js"}],8:[function(t,e,r){var n=t("bignumber.js"),o={wei:"1",kwei:"1000",ada:"1000",mwei:"1000000",babbage:"1000000",gwei:"1000000000",shannon:"1000000000",szabo:"1000000000000",finney:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},i=function(t,e,r){return new Array(e-t.length+1).join(r?r:"0")+t},a=function(t){var e="",r=0,n=t.length;for("0x"===t.substring(0,2)&&(r=2);n>r;r+=2){var o=parseInt(t.substr(r,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},s=function(t){for(var e="",r=0;rthis._inputTypes.length&&i.isObject(t[t.length-1])&&(e=t.pop()),e.to=this._address,e.data="0x"+this.signature()+o.encodeParams(this._inputTypes,t),e},a.prototype.signature=function(){return n.sha3(n.fromAscii(this._name)).slice(2,10)},a.prototype.call=function(){var t=this.toPayload.apply(this,Array.prototype.slice.call(arguments)),e=n.eth.call(t);e=e.length>=2?e.slice(2):e;var r=o.decodeParams(this._outputTypes,e);return 1===r.length?r[0]:r},a.prototype.sendTransaction=function(){var t=this.toPayload.apply(this,Array.prototype.slice.call(arguments));n.eth.sendTransaction(t)},a.prototype.displayName=function(){return i.extractDisplayName(this._name)},a.prototype.typeName=function(){return i.extractTypeName(this._name)},a.prototype.execute=function(){var t=!this._constant;return t?this.sendTransaction.apply(this,Array.prototype.slice.call(arguments)):this.call.apply(this,Array.prototype.slice.call(arguments))},a.prototype.attachToContract=function(t){var e=this.execute.bind(this);e.call=this.call.bind(this),e.sendTransaction=this.sendTransaction.bind(this);var r=this.displayName();t[r]||(t[r]=e),t[r][this.typeName()]=e},e.exports=a},{"../solidity/coder":2,"../utils/utils":8,"../web3":10}],19:[function(t,e,r){"use strict";var n=t("xmlhttprequest").XMLHttpRequest,o=t("./errors"),i=function(t){this.host=t||"http://localhost:8545"};i.prototype.send=function(t){var e=new n;e.open("POST",this.host,!1);try{e.send(JSON.stringify(t))}catch(r){throw o.InvalidConnection(this.host)}return JSON.parse(e.responseText)},i.prototype.sendAsync=function(t,e){var r=new n;r.onreadystatechange=function(){4===r.readyState&&e(null,JSON.parse(r.responseText))},r.open("POST",this.host,!0);try{r.send(JSON.stringify(t))}catch(i){e(o.InvalidConnection(this.host))}},e.exports=i},{"./errors":13,xmlhttprequest:6}],20:[function(t,e,r){var n=function(){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,void(this.messageId=1))};n.getInstance=function(){var t=new n;return t},n.prototype.toPayload=function(t,e){return t||console.error("jsonrpc method should be specified!"),{jsonrpc:"2.0",method:t,params:e||[],id:this.messageId++}},n.prototype.isValidResponse=function(t){return!!t&&!t.error&&"2.0"===t.jsonrpc&&"number"==typeof t.id&&void 0!==t.result},n.prototype.toBatchPayload=function(t){var e=this;return t.map(function(t){return e.toPayload(t.method,t.params)})},e.exports=n},{}],21:[function(t,e,r){var n=t("./requestmanager"),o=t("../utils/utils"),i=t("./errors"),a=function(t){this.name=t.name,this.call=t.call,this.params=t.params||0,this.inputFormatter=t.inputFormatter,this.outputFormatter=t.outputFormatter};a.prototype.getCall=function(t){return o.isFunction(this.call)?this.call(t):this.call},a.prototype.extractCallback=function(t){return o.isFunction(t[t.length-1])?t.pop():null},a.prototype.validateArgs=function(t){if(t.length!==this.params)throw i.InvalidNumberOfParams()},a.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter.map(function(e,r){return e?e(t[r]):t[r]}):t},a.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},a.prototype.attachToObject=function(t){var e=this.send.bind(this);e.call=this.call;var r=this.name.split(".");r.length>1?(t[r[0]]=t[r[0]]||{},t[r[0]][r[1]]=e):t[r[0]]=e},a.prototype.toPayload=function(t){var e=this.getCall(t),r=this.extractCallback(t),n=this.formatInput(t);return this.validateArgs(n),{method:e,params:n,callback:r}},a.prototype.send=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));if(t.callback){var e=this;return n.getInstance().sendAsync(t,function(r,n){t.callback(null,e.formatOutput(n))})}return this.formatOutput(n.getInstance().send(t))},e.exports=a},{"../utils/utils":8,"./errors":13,"./requestmanager":25}],22:[function(t,e,r){var n=t("../utils/utils"),o=t("./property"),i=[],a=[new o({name:"listening",getter:"net_listening"}),new o({name:"peerCount",getter:"net_peerCount",outputFormatter:n.toDecimal})];e.exports={methods:i,properties:a}},{"../utils/utils":8,"./property":23}],23:[function(t,e,r){var n=t("./requestmanager"),o=function(t){this.name=t.name,this.getter=t.getter,this.setter=t.setter,this.outputFormatter=t.outputFormatter,this.inputFormatter=t.inputFormatter};o.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter(t):t},o.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},o.prototype.attachToObject=function(t){var e={get:this.get.bind(this),set:this.set.bind(this)},r=this.name.split(".");r.length>1?(t[r[0]]=t[r[0]]||{},Object.defineProperty(t[r[0]],r[1],e)):Object.defineProperty(t,r[0],e)},o.prototype.get=function(){return this.formatOutput(n.getInstance().send({method:this.getter}))},o.prototype.set=function(t){return n.getInstance().send({method:this.setter,params:[this.formatInput(t)]})},e.exports=o},{"./requestmanager":25}],24:[function(t,e,r){var n=function(){};n.prototype.send=function(t){var e=navigator.qt.callMethod(JSON.stringify(t));return JSON.parse(e)},e.exports=n},{}],25:[function(t,e,r){var n=t("./jsonrpc"),o=t("../utils/utils"),i=t("../utils/config"),a=t("./errors"),s=function(t){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,this.provider=t,this.polls=[],this.timeout=null,void this.poll())};s.getInstance=function(){var t=new s;return t},s.prototype.send=function(t){if(!this.provider)return console.error(a.InvalidProvider()),null;var e=n.getInstance().toPayload(t.method,t.params),r=this.provider.send(e);if(!n.getInstance().isValidResponse(r))throw a.InvalidResponse(r);return r.result},s.prototype.sendAsync=function(t,e){if(!this.provider)return e(a.InvalidProvider());var r=n.getInstance().toPayload(t.method,t.params);this.provider.sendAsync(r,function(t,r){return t?e(t):n.getInstance().isValidResponse(r)?void e(null,r.result):e(a.InvalidResponse(r))})},s.prototype.setProvider=function(t){this.provider=t},s.prototype.startPolling=function(t,e,r,n){this.polls.push({data:t,id:e,callback:r,uninstall:n})},s.prototype.stopPolling=function(t){for(var e=this.polls.length;e--;){var r=this.polls[e];r.id===t&&this.polls.splice(e,1)}},s.prototype.reset=function(){this.polls.forEach(function(t){t.uninstall(t.id)}),this.polls=[],this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.poll()},s.prototype.poll=function(){if(this.timeout=setTimeout(this.poll.bind(this),i.ETH_POLLING_TIMEOUT),this.polls.length){if(!this.provider)return void console.error(a.InvalidProvider());var t=n.getInstance().toBatchPayload(this.polls.map(function(t){return t.data})),e=this;this.provider.sendAsync(t,function(t,r){if(!t){if(!o.isArray(r))throw a.InvalidResponse(r);r.map(function(t,r){return t.callback=e.polls[r].callback,t}).filter(function(t){var e=n.getInstance().isValidResponse(t);return e||t.callback(a.InvalidResponse(t)),e}).filter(function(t){return o.isArray(t.result)&&t.result.length>0}).forEach(function(t){t.callback(null,t.result)})}})}},e.exports=s},{"../utils/config":7,"../utils/utils":8,"./errors":13,"./jsonrpc":20}],26:[function(t,e,r){var n=t("./method"),o=t("./formatters"),i=new n({name:"post",call:"shh_post",params:1,inputFormatter:[o.inputPostFormatter]}),a=new n({name:"newIdentity",call:"shh_newIdentity",params:0}),s=new n({name:"hasIdentity",call:"shh_hasIdentity",params:1}),u=new n({name:"newGroup",call:"shh_newGroup",params:0}),c=new n({name:"addToGroup",call:"shh_addToGroup",params:0}),l=[i,a,s,u,c];e.exports={methods:l}},{"./formatters":17,"./method":21}],27:[function(t,e,r){var n=t("./method"),o=function(){var t=function(t){return"string"==typeof t[0]?"eth_newBlockFilter":"eth_newFilter"},e=new n({name:"newFilter",call:t,params:1}),r=new n({name:"uninstallFilter",call:"eth_uninstallFilter",params:1}),o=new n({name:"getLogs",call:"eth_getFilterLogs",params:1}),i=new n({name:"poll",call:"eth_getFilterChanges",params:1 -});return[e,r,o,i]},i=function(){var t=new n({name:"newFilter",call:"shh_newFilter",params:1}),e=new n({name:"uninstallFilter",call:"shh_uninstallFilter",params:1}),r=new n({name:"getLogs",call:"shh_getMessages",params:1}),o=new n({name:"poll",call:"shh_getFilterChanges",params:1});return[t,e,r,o]};e.exports={eth:o,shh:i}},{"./method":21}],28:[function(t,e,r){},{}],"bignumber.js":[function(t,e,r){"use strict";e.exports=BigNumber},{}],web3:[function(t,e,r){var n=t("./lib/web3");n.providers.HttpProvider=t("./lib/web3/httpprovider"),n.providers.QtSyncProvider=t("./lib/web3/qtsync"),n.eth.contract=t("./lib/web3/contract"),n.abi=t("./lib/solidity/abi"),"undefined"!=typeof window&&"undefined"==typeof window.web3&&(window.web3=n),e.exports=n},{"./lib/solidity/abi":1,"./lib/web3":10,"./lib/web3/contract":11,"./lib/web3/httpprovider":19,"./lib/web3/qtsync":24}]},{},["web3"]); \ No newline at end of file +require=function t(e,r,n){function o(a,s){if(!r[a]){if(!e[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=r[a]={exports:{}};e[a][0].call(l.exports,function(t){var r=e[a][1][t];return o(r?r:t)},l,l.exports,t,e,r,n)}return r[a].exports}for(var i="function"==typeof require&&require,a=0;a0&&console.warn("didn't found matching constructor, using default one"),"")};e.exports={formatConstructorParams:i}},{"./coder":2,"./utils":5}],2:[function(t,e,r){var n=t("bignumber.js"),o=t("../utils/utils"),i=t("./formatters"),a=t("./param"),s=function(t){return"[]"===t.slice(-2)},u=function(t){this._name=t.name,this._match=t.match,this._mode=t.mode,this._inputFormatter=t.inputFormatter,this._outputFormatter=t.outputFormatter};u.prototype.isType=function(t){return"strict"===this._match?this._name===t||0===t.indexOf(this._name)&&"[]"===t.slice(this._name.length):"prefix"===this._match?0===t.indexOf(this._name):void 0},u.prototype.formatInput=function(t,e){if(o.isArray(t)&&e){var r=this;return t.map(function(t){return r._inputFormatter(t)}).reduce(function(t,e){return t.combine(e)},i.formatInputInt(t.length)).withOffset(32)}return this._inputFormatter(t)},u.prototype.formatOutput=function(t,e){if(e){for(var r=[],o=new n(t.dynamicPart().slice(0,64),16),i=0;64*o>i;i+=64)r.push(this._outputFormatter(new a(t.dynamicPart().substr(i+64,64))));return r}return this._outputFormatter(t)},u.prototype.sliceParam=function(t,e,r){return"bytes"===this._mode?a.decodeBytes(t,e):s(r)?a.decodeArray(t,e):a.decodeParam(t,e)};var c=function(t){this._types=t};c.prototype._requireType=function(t){var e=this._types.filter(function(e){return e.isType(t)})[0];if(!e)throw Error("invalid solidity type!: "+t);return e},c.prototype._formatInput=function(t,e){return this._requireType(t).formatInput(e,s(t))},c.prototype.encodeParam=function(t,e){return this._formatInput(t,e).encode()},c.prototype.encodeParams=function(t,e){var r=this,n=t.map(function(t,n){return r._formatInput(t,e[n])});return a.encodeList(n)},c.prototype.decodeParam=function(t,e){return this.decodeParams([t],e)[0]},c.prototype.decodeParams=function(t,e){var r=this;return t.map(function(t,n){var o=r._requireType(t),i=o.sliceParam(e,n,t);return o.formatOutput(i,s(t))})};var l=new c([new u({name:"address",match:"strict",mode:"value",inputFormatter:i.formatInputInt,outputFormatter:i.formatOutputAddress}),new u({name:"bool",match:"strict",mode:"value",inputFormatter:i.formatInputBool,outputFormatter:i.formatOutputBool}),new u({name:"int",match:"prefix",mode:"value",inputFormatter:i.formatInputInt,outputFormatter:i.formatOutputInt}),new u({name:"uint",match:"prefix",mode:"value",inputFormatter:i.formatInputInt,outputFormatter:i.formatOutputUInt}),new u({name:"bytes",match:"strict",mode:"bytes",inputFormatter:i.formatInputDynamicBytes,outputFormatter:i.formatOutputDynamicBytes}),new u({name:"bytes",match:"prefix",mode:"value",inputFormatter:i.formatInputBytes,outputFormatter:i.formatOutputBytes}),new u({name:"real",match:"prefix",mode:"value",inputFormatter:i.formatInputReal,outputFormatter:i.formatOutputReal}),new u({name:"ureal",match:"prefix",mode:"value",inputFormatter:i.formatInputReal,outputFormatter:i.formatOutputUReal})]);e.exports=l},{"../utils/utils":8,"./formatters":3,"./param":4,"bignumber.js":"bignumber.js"}],3:[function(t,e,r){var n=t("bignumber.js"),o=t("../utils/utils"),i=t("../utils/config"),a=t("./param"),s=function(t){var e=2*i.ETH_PADDING;n.config(i.ETH_BIGNUMBER_ROUNDING_MODE);var r=o.padLeft(o.toTwosComplement(t).round().toString(16),e);return new a(r)},u=function(t){var e=o.fromAscii(t,i.ETH_PADDING).substr(2);return new a(e)},c=function(t){var e=o.fromAscii(t,i.ETH_PADDING).substr(2);return new a(s(t.length).value+e,32)},l=function(t){var e="000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0");return new a(e)},p=function(t){return s(new n(t).times(new n(2).pow(128)))},f=function(t){return"1"===new n(t.substr(0,1),16).toString(2).substr(0,1)},m=function(t){var e=t.staticPart()||"0";return f(e)?new n(e,16).minus(new n("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new n(e,16)},h=function(t){var e=t.staticPart()||"0";return new n(e,16)},d=function(t){return m(t).dividedBy(new n(2).pow(128))},y=function(t){return h(t).dividedBy(new n(2).pow(128))},g=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t.staticPart()?!0:!1},b=function(t){return o.toAscii(t.staticPart())},v=function(t){return o.toAscii(t.dynamicPart().slice(64))},w=function(t){var e=t.staticPart();return"0x"+e.slice(e.length-40,e.length)};e.exports={formatInputInt:s,formatInputBytes:u,formatInputDynamicBytes:c,formatInputBool:l,formatInputReal:p,formatOutputInt:m,formatOutputUInt:h,formatOutputReal:d,formatOutputUReal:y,formatOutputBool:g,formatOutputBytes:b,formatOutputDynamicBytes:v,formatOutputAddress:w}},{"../utils/config":7,"../utils/utils":8,"./param":4,"bignumber.js":"bignumber.js"}],4:[function(t,e,r){var n=t("../utils/utils"),o=function(t,e){this.value=t||"",this.offset=e};o.prototype.dynamicPartLength=function(){return this.dynamicPart().length/2},o.prototype.withOffset=function(t){return new o(this.value,t)},o.prototype.combine=function(t){return new o(this.value+t.value)},o.prototype.isDynamic=function(){return this.value.length>64},o.prototype.offsetAsBytes=function(){return this.isDynamic()?n.padLeft(n.toTwosComplement(this.offset).toString(16),64):""},o.prototype.staticPart=function(){return this.isDynamic()?this.offsetAsBytes():this.value},o.prototype.dynamicPart=function(){return this.isDynamic()?this.value:""},o.prototype.encode=function(){return this.staticPart()+this.dynamicPart()},o.encodeList=function(t){var e=32*t.length,r=t.map(function(t){if(!t.isDynamic())return t;var r=e;return e+=t.dynamicPartLength(),t.withOffset(r)});return r.reduce(function(t,e){return t+e.dynamicPart()},r.reduce(function(t,e){return t+e.staticPart()},""))},o.decodeParam=function(t,e){return e=e||0,new o(t.substr(64*e,64))};var i=function(t,e){return parseInt("0x"+t.substr(64*e,64))};o.decodeBytes=function(t,e){e=e||0;var r=i(t,e);return new o(t.substr(2*r,128))},o.decodeArray=function(t,e){e=e||0;var r=i(t,e),n=parseInt("0x"+t.substr(2*r,64));return new o(t.substr(2*r,64*(n+1)))},e.exports=o},{"../utils/utils":8}],5:[function(t,e,r){var n=function(t,e){return t.filter(function(t){return"constructor"===t.type&&t.inputs.length===e})[0]};e.exports={getConstructor:n}},{}],6:[function(t,e,r){"use strict";r.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],7:[function(t,e,r){var n=t("bignumber.js"),o=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:o,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:n.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3,defaultBlock:"latest",defaultAccount:void 0}},{"bignumber.js":"bignumber.js"}],8:[function(t,e,r){var n=t("bignumber.js"),o={wei:"1",kwei:"1000",ada:"1000",mwei:"1000000",babbage:"1000000",gwei:"1000000000",shannon:"1000000000",szabo:"1000000000000",finney:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},i=function(t,e,r){return new Array(e-t.length+1).join(r?r:"0")+t},a=function(t){var e="",r=0,n=t.length;for("0x"===t.substring(0,2)&&(r=2);n>r;r+=2){var o=parseInt(t.substr(r,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},s=function(t){for(var e="",r=0;rthis._inputTypes.length&&i.isObject(t[t.length-1])&&(e=t.pop()),e.to=this._address,e.data="0x"+this.signature()+o.encodeParams(this._inputTypes,t),e},a.prototype.signature=function(){return n.sha3(n.fromAscii(this._name)).slice(2,10)},a.prototype.call=function(){var t=this.toPayload.apply(this,Array.prototype.slice.call(arguments)),e=n.eth.call(t);e=e.length>=2?e.slice(2):e;var r=o.decodeParams(this._outputTypes,e);return 1===r.length?r[0]:r},a.prototype.sendTransaction=function(){var t=this.toPayload.apply(this,Array.prototype.slice.call(arguments));n.eth.sendTransaction(t)},a.prototype.displayName=function(){return i.extractDisplayName(this._name)},a.prototype.typeName=function(){return i.extractTypeName(this._name)},a.prototype.execute=function(){var t=!this._constant;return t?this.sendTransaction.apply(this,Array.prototype.slice.call(arguments)):this.call.apply(this,Array.prototype.slice.call(arguments))},a.prototype.attachToContract=function(t){var e=this.execute.bind(this);e.call=this.call.bind(this),e.sendTransaction=this.sendTransaction.bind(this);var r=this.displayName();t[r]||(t[r]=e),t[r][this.typeName()]=e},e.exports=a},{"../solidity/coder":2,"../utils/utils":8,"../web3":10}],19:[function(t,e,r){"use strict";var n=t("xmlhttprequest").XMLHttpRequest,o=t("./errors"),i=function(t){this.host=t||"http://localhost:8545"};i.prototype.send=function(t){var e=new n;e.open("POST",this.host,!1);try{e.send(JSON.stringify(t))}catch(r){throw o.InvalidConnection(this.host)}var i=e.responseText;try{i=JSON.parse(i)}catch(a){throw o.InvalidResponse(i)}return i},i.prototype.sendAsync=function(t,e){var r=new n;r.onreadystatechange=function(){if(4===r.readyState){var t=r.responseText,n=null;try{t=JSON.parse(t)}catch(i){n=o.InvalidResponse(t)}e(n,t)}},r.open("POST",this.host,!0);try{r.send(JSON.stringify(t))}catch(i){e(o.InvalidConnection(this.host))}},e.exports=i},{"./errors":13,xmlhttprequest:6}],20:[function(t,e,r){var n=function(){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,void(this.messageId=1))};n.getInstance=function(){var t=new n;return t},n.prototype.toPayload=function(t,e){return t||console.error("jsonrpc method should be specified!"),{jsonrpc:"2.0",method:t,params:e||[],id:this.messageId++}},n.prototype.isValidResponse=function(t){return!!t&&!t.error&&"2.0"===t.jsonrpc&&"number"==typeof t.id&&void 0!==t.result},n.prototype.toBatchPayload=function(t){var e=this;return t.map(function(t){return e.toPayload(t.method,t.params)})},e.exports=n},{}],21:[function(t,e,r){var n=t("./requestmanager"),o=t("../utils/utils"),i=t("./errors"),a=function(t){this.name=t.name,this.call=t.call,this.params=t.params||0,this.inputFormatter=t.inputFormatter,this.outputFormatter=t.outputFormatter};a.prototype.getCall=function(t){return o.isFunction(this.call)?this.call(t):this.call},a.prototype.extractCallback=function(t){return o.isFunction(t[t.length-1])?t.pop():null},a.prototype.validateArgs=function(t){if(t.length!==this.params)throw i.InvalidNumberOfParams()},a.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter.map(function(e,r){return e?e(t[r]):t[r]}):t},a.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},a.prototype.attachToObject=function(t){var e=this.send.bind(this);e.call=this.call;var r=this.name.split(".");r.length>1?(t[r[0]]=t[r[0]]||{},t[r[0]][r[1]]=e):t[r[0]]=e},a.prototype.toPayload=function(t){var e=this.getCall(t),r=this.extractCallback(t),n=this.formatInput(t);return this.validateArgs(n),{method:e,params:n,callback:r}},a.prototype.send=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));if(t.callback){var e=this;return n.getInstance().sendAsync(t,function(r,n){t.callback(null,e.formatOutput(n))})}return this.formatOutput(n.getInstance().send(t))},e.exports=a},{"../utils/utils":8,"./errors":13,"./requestmanager":25}],22:[function(t,e,r){var n=t("../utils/utils"),o=t("./property"),i=[],a=[new o({name:"listening",getter:"net_listening"}),new o({name:"peerCount",getter:"net_peerCount",outputFormatter:n.toDecimal})];e.exports={methods:i,properties:a}},{"../utils/utils":8,"./property":23}],23:[function(t,e,r){var n=t("./requestmanager"),o=function(t){this.name=t.name,this.getter=t.getter,this.setter=t.setter,this.outputFormatter=t.outputFormatter,this.inputFormatter=t.inputFormatter};o.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter(t):t},o.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},o.prototype.attachToObject=function(t){var e={get:this.get.bind(this),set:this.set.bind(this)},r=this.name.split(".");r.length>1?(t[r[0]]=t[r[0]]||{},Object.defineProperty(t[r[0]],r[1],e)):Object.defineProperty(t,r[0],e)},o.prototype.get=function(){return this.formatOutput(n.getInstance().send({method:this.getter}))},o.prototype.set=function(t){return n.getInstance().send({method:this.setter,params:[this.formatInput(t)]})},e.exports=o},{"./requestmanager":25}],24:[function(t,e,r){var n=function(){};n.prototype.send=function(t){var e=navigator.qt.callMethod(JSON.stringify(t));return JSON.parse(e)},e.exports=n},{}],25:[function(t,e,r){var n=t("./jsonrpc"),o=t("../utils/utils"),i=t("../utils/config"),a=t("./errors"),s=function(t){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,this.provider=t,this.polls=[],this.timeout=null,void this.poll())};s.getInstance=function(){var t=new s;return t},s.prototype.send=function(t){if(!this.provider)return console.error(a.InvalidProvider()),null;var e=n.getInstance().toPayload(t.method,t.params),r=this.provider.send(e);if(!n.getInstance().isValidResponse(r))throw a.InvalidResponse(r);return r.result},s.prototype.sendAsync=function(t,e){if(!this.provider)return e(a.InvalidProvider());var r=n.getInstance().toPayload(t.method,t.params);this.provider.sendAsync(r,function(t,r){return t?e(t):n.getInstance().isValidResponse(r)?void e(null,r.result):e(a.InvalidResponse(r))})},s.prototype.setProvider=function(t){this.provider=t},s.prototype.startPolling=function(t,e,r,n){this.polls.push({data:t,id:e,callback:r,uninstall:n})},s.prototype.stopPolling=function(t){for(var e=this.polls.length;e--;){var r=this.polls[e];r.id===t&&this.polls.splice(e,1)}},s.prototype.reset=function(){this.polls.forEach(function(t){t.uninstall(t.id)}),this.polls=[],this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.poll()},s.prototype.poll=function(){if(this.timeout=setTimeout(this.poll.bind(this),i.ETH_POLLING_TIMEOUT),this.polls.length){if(!this.provider)return void console.error(a.InvalidProvider());var t=n.getInstance().toBatchPayload(this.polls.map(function(t){return t.data})),e=this;this.provider.sendAsync(t,function(t,r){if(!t){if(!o.isArray(r))throw a.InvalidResponse(r);r.map(function(t,r){return t.callback=e.polls[r].callback,t}).filter(function(t){var e=n.getInstance().isValidResponse(t);return e||t.callback(a.InvalidResponse(t)),e}).filter(function(t){return o.isArray(t.result)&&t.result.length>0}).forEach(function(t){t.callback(null,t.result)})}})}},e.exports=s},{"../utils/config":7,"../utils/utils":8,"./errors":13,"./jsonrpc":20}],26:[function(t,e,r){var n=t("./method"),o=t("./formatters"),i=new n({name:"post",call:"shh_post",params:1,inputFormatter:[o.inputPostFormatter]}),a=new n({name:"newIdentity",call:"shh_newIdentity",params:0}),s=new n({name:"hasIdentity",call:"shh_hasIdentity",params:1}),u=new n({name:"newGroup",call:"shh_newGroup",params:0}),c=new n({name:"addToGroup",call:"shh_addToGroup",params:0}),l=[i,a,s,u,c];e.exports={methods:l}},{"./formatters":17,"./method":21}],27:[function(t,e,r){var n=t("./method"),o=function(){var t=function(t){return"string"==typeof t[0]?"eth_newBlockFilter":"eth_newFilter"},e=new n({name:"newFilter",call:t,params:1}),r=new n({name:"uninstallFilter",call:"eth_uninstallFilter",params:1}),o=new n({name:"getLogs",call:"eth_getFilterLogs",params:1}),i=new n({name:"poll",call:"eth_getFilterChanges",params:1});return[e,r,o,i]},i=function(){var t=new n({name:"newFilter",call:"shh_newFilter",params:1}),e=new n({name:"uninstallFilter",call:"shh_uninstallFilter",params:1}),r=new n({name:"getLogs",call:"shh_getMessages",params:1}),o=new n({name:"poll",call:"shh_getFilterChanges",params:1 +});return[t,e,r,o]};e.exports={eth:o,shh:i}},{"./method":21}],28:[function(t,e,r){},{}],"bignumber.js":[function(t,e,r){"use strict";e.exports=BigNumber},{}],web3:[function(t,e,r){var n=t("./lib/web3");n.providers.HttpProvider=t("./lib/web3/httpprovider"),n.providers.QtSyncProvider=t("./lib/web3/qtsync"),n.eth.contract=t("./lib/web3/contract"),n.abi=t("./lib/solidity/abi"),"undefined"!=typeof window&&"undefined"==typeof window.web3&&(window.web3=n),e.exports=n},{"./lib/solidity/abi":1,"./lib/web3":10,"./lib/web3/contract":11,"./lib/web3/httpprovider":19,"./lib/web3/qtsync":24}]},{},["web3"]); \ No newline at end of file diff --git a/libjsqrc/ethereumjs/dist/web3.js b/libjsqrc/ethereumjs/dist/web3.js index db554daea..ec66a38d8 100644 --- a/libjsqrc/ethereumjs/dist/web3.js +++ b/libjsqrc/ethereumjs/dist/web3.js @@ -22,118 +22,29 @@ require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof requ * @date 2014 */ -var utils = require('../utils/utils'); var coder = require('./coder'); -var solUtils = require('./utils'); - -/** - * Formats input params to bytes - * - * @method formatInput - * @param {Array} abi inputs of method - * @param {Array} params that will be formatted to bytes - * @returns bytes representation of input params - */ -var formatInput = function (inputs, params) { - var i = inputs.map(function (input) { - return input.type; - }); - return coder.encodeParams(i, params); -}; - -/** - * Formats output bytes back to param list - * - * @method formatOutput - * @param {Array} abi outputs of method - * @param {String} bytes represention of output - * @returns {Array} output params - */ -var formatOutput = function (outs, bytes) { - var o = outs.map(function (out) { - return out.type; - }); - - return coder.decodeParams(o, bytes); -}; - -/** - * Should be called to create input parser for contract with given abi - * - * @method inputParser - * @param {Array} contract abi - * @returns {Object} input parser object for given json abi - * TODO: refactor creating the parser, do not double logic from contract - */ -var inputParser = function (json) { - var parser = {}; - json.forEach(function (method) { - var displayName = utils.extractDisplayName(method.name); - var typeName = utils.extractTypeName(method.name); - - var impl = function () { - var params = Array.prototype.slice.call(arguments); - return formatInput(method.inputs, params); - }; - - if (parser[displayName] === undefined) { - parser[displayName] = impl; - } - - parser[displayName][typeName] = impl; - }); - - return parser; -}; - -/** - * Should be called to create output parser for contract with given abi - * - * @method outputParser - * @param {Array} contract abi - * @returns {Object} output parser for given json abi - */ -var outputParser = function (json) { - var parser = {}; - json.forEach(function (method) { - - var displayName = utils.extractDisplayName(method.name); - var typeName = utils.extractTypeName(method.name); - - var impl = function (output) { - return formatOutput(method.outputs, output); - }; - - if (parser[displayName] === undefined) { - parser[displayName] = impl; - } - - parser[displayName][typeName] = impl; - }); - - return parser; -}; +var utils = require('./utils'); var formatConstructorParams = function (abi, params) { - var constructor = solUtils.getConstructor(abi, params.length); + var constructor = utils.getConstructor(abi, params.length); if (!constructor) { if (params.length > 0) { console.warn("didn't found matching constructor, using default one"); } return ''; } - return formatInput(constructor.inputs, params); + + return coder.encodeParams(constructor.inputs.map(function (input) { + return input.type; + }), params); }; module.exports = { - inputParser: inputParser, - outputParser: outputParser, - formatInput: formatInput, - formatOutput: formatOutput, formatConstructorParams: formatConstructorParams }; -},{"../utils/utils":8,"./coder":2,"./utils":5}],2:[function(require,module,exports){ + +},{"./coder":2,"./utils":5}],2:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -213,9 +124,8 @@ SolidityType.prototype.formatInput = function (param, arrayType) { return param.map(function (p) { return self._inputFormatter(p); }).reduce(function (acc, current) { - acc.appendArrayElement(current); - return acc; - }, new SolidityParam('', f.formatInputInt(param.length).value)); + return acc.combine(current); + }, f.formatInputInt(param.length)).withOffset(32); } return this._inputFormatter(param); }; @@ -232,9 +142,9 @@ SolidityType.prototype.formatOutput = function (param, arrayType) { if (arrayType) { // let's assume, that we solidity will never return long arrays :P var result = []; - var length = new BigNumber(param.prefix, 16); + var length = new BigNumber(param.dynamicPart().slice(0, 64), 16); for (var i = 0; i < length * 64; i += 64) { - result.push(this._outputFormatter(new SolidityParam(param.suffix.slice(i, i + 64)))); + result.push(this._outputFormatter(new SolidityParam(param.dynamicPart().substr(i + 64, 64)))); } return result; } @@ -242,31 +152,21 @@ SolidityType.prototype.formatOutput = function (param, arrayType) { }; /** - * Should be used to check if a type is variadic + * Should be used to slice single param from bytes * - * @method isVariadicType - * @param {String} type - * @returns {Bool} true if the type is variadic - */ -SolidityType.prototype.isVariadicType = function (type) { - return isArrayType(type) || this._mode === 'bytes'; -}; - -/** - * Should be used to shift param from params group - * - * @method shiftParam + * @method sliceParam + * @param {String} bytes + * @param {Number} index of param to slice * @param {String} type - * @returns {SolidityParam} shifted param + * @returns {SolidityParam} param */ -SolidityType.prototype.shiftParam = function (type, param) { +SolidityType.prototype.sliceParam = function (bytes, index, type) { if (this._mode === 'bytes') { - return param.shiftBytes(); + return SolidityParam.decodeBytes(bytes, index); } else if (isArrayType(type)) { - var length = new BigNumber(param.prefix.slice(0, 64), 16); - return param.shiftArray(length); + return SolidityParam.decodeArray(bytes, index); } - return param.shiftValue(); + return SolidityParam.decodeParam(bytes, index); }; /** @@ -296,28 +196,6 @@ SolidityCoder.prototype._requireType = function (type) { return solidityType; }; -/** - * Should be used to transform plain bytes to SolidityParam object - * - * @method _bytesToParam - * @param {Array} types of params - * @param {String} bytes to be transformed to SolidityParam - * @return {SolidityParam} SolidityParam for this group of params - */ -SolidityCoder.prototype._bytesToParam = function (types, bytes) { - var self = this; - var prefixTypes = types.reduce(function (acc, type) { - return self._requireType(type).isVariadicType(type) ? acc + 1 : acc; - }, 0); - var valueTypes = types.length - prefixTypes; - - var prefix = bytes.slice(0, prefixTypes * 64); - bytes = bytes.slice(prefixTypes * 64); - var value = bytes.slice(0, valueTypes * 64); - var suffix = bytes.slice(valueTypes * 64); - return new SolidityParam(value, prefix, suffix); -}; - /** * Should be used to transform plain param of given type to SolidityParam * @@ -352,24 +230,11 @@ SolidityCoder.prototype.encodeParam = function (type, param) { */ SolidityCoder.prototype.encodeParams = function (types, params) { var self = this; - return types.map(function (type, index) { + var solidityParams = types.map(function (type, index) { return self._formatInput(type, params[index]); - }).reduce(function (acc, solidityParam) { - acc.append(solidityParam); - return acc; - }, new SolidityParam()).encode(); -}; + }); -/** - * Should be used to transform SolidityParam to plain param - * - * @method _formatOutput - * @param {String} type - * @param {SolidityParam} param - * @return {Object} plain param - */ -SolidityCoder.prototype._formatOutput = function (type, param) { - return this._requireType(type).formatOutput(param, isArrayType(type)); + return SolidityParam.encodeList(solidityParams); }; /** @@ -381,7 +246,7 @@ SolidityCoder.prototype._formatOutput = function (type, param) { * @return {Object} plain param */ SolidityCoder.prototype.decodeParam = function (type, bytes) { - return this._formatOutput(type, this._bytesToParam([type], bytes)); + return this.decodeParams([type], bytes)[0]; }; /** @@ -394,10 +259,9 @@ SolidityCoder.prototype.decodeParam = function (type, bytes) { */ SolidityCoder.prototype.decodeParams = function (types, bytes) { var self = this; - var param = this._bytesToParam(types, bytes); - return types.map(function (type) { + return types.map(function (type, index) { var solidityType = self._requireType(type); - var p = solidityType.shiftParam(type, param); + var p = solidityType.sliceParam(bytes, index, type); return solidityType.formatOutput(p, isArrayType(type)); }); }; @@ -530,7 +394,7 @@ var formatInputBytes = function (value) { */ var formatInputDynamicBytes = function (value) { var result = utils.fromAscii(value, c.ETH_PADDING).substr(2); - return new SolidityParam('', formatInputInt(value.length).value, result); + return new SolidityParam(formatInputInt(value.length).value + result, 32); }; /** @@ -576,7 +440,7 @@ var signedIsNegative = function (value) { * @returns {BigNumber} right-aligned output bytes formatted to big number */ var formatOutputInt = function (param) { - var value = param.value || "0"; + var value = param.staticPart() || "0"; // check if it's negative number // it it is, return two's complement @@ -594,7 +458,7 @@ var formatOutputInt = function (param) { * @returns {BigNumeber} right-aligned output bytes formatted to uint */ var formatOutputUInt = function (param) { - var value = param.value || "0"; + var value = param.staticPart() || "0"; return new BigNumber(value, 16); }; @@ -628,7 +492,7 @@ var formatOutputUReal = function (param) { * @returns {Boolean} right-aligned input bytes formatted to bool */ var formatOutputBool = function (param) { - return param.value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false; + return param.staticPart() === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false; }; /** @@ -640,7 +504,7 @@ var formatOutputBool = function (param) { */ var formatOutputBytes = function (param) { // length might also be important! - return utils.toAscii(param.value); + return utils.toAscii(param.staticPart()); }; /** @@ -652,7 +516,7 @@ var formatOutputBytes = function (param) { */ var formatOutputDynamicBytes = function (param) { // length might also be important! - return utils.toAscii(param.suffix); + return utils.toAscii(param.dynamicPart().slice(64)); }; /** @@ -663,7 +527,7 @@ var formatOutputDynamicBytes = function (param) { * @returns {String} address */ var formatOutputAddress = function (param) { - var value = param.value; + var value = param.staticPart(); return "0x" + value.slice(value.length - 40, value.length); }; @@ -707,91 +571,196 @@ module.exports = { * @date 2015 */ +var utils = require('../utils/utils'); + /** * SolidityParam object prototype. * Should be used when encoding, decoding solidity bytes */ -var SolidityParam = function (value, prefix, suffix) { - this.prefix = prefix || ''; +var SolidityParam = function (value, offset) { this.value = value || ''; - this.suffix = suffix || ''; + this.offset = offset; // offset in bytes +}; + +/** + * This method should be used to get length of params's dynamic part + * + * @method dynamicPartLength + * @returns {Number} length of dynamic part (in bytes) + */ +SolidityParam.prototype.dynamicPartLength = function () { + return this.dynamicPart().length / 2; +}; + +/** + * This method should be used to create copy of solidity param with different offset + * + * @method withOffset + * @param {Number} offset length in bytes + * @returns {SolidityParam} new solidity param with applied offset + */ +SolidityParam.prototype.withOffset = function (offset) { + return new SolidityParam(this.value, offset); }; /** - * This method should be used to encode two params one after another + * This method should be used to combine solidity params together + * eg. when appending an array * - * @method append - * @param {SolidityParam} param that it appended after this + * @method combine + * @param {SolidityParam} param with which we should combine + * @param {SolidityParam} result of combination */ -SolidityParam.prototype.append = function (param) { - this.prefix += param.prefix; - this.value += param.value; - this.suffix += param.suffix; +SolidityParam.prototype.combine = function (param) { + return new SolidityParam(this.value + param.value); }; /** - * This method should be used to encode next param in an array + * This method should be called to check if param has dynamic size. + * If it has, it returns true, otherwise false * - * @method appendArrayElement - * @param {SolidityParam} param that is appended to an array + * @method isDynamic + * @returns {Boolean} */ -SolidityParam.prototype.appendArrayElement = function (param) { - this.suffix += param.value; - this.prefix += param.prefix; - // TODO: suffix not supported = it's required for nested arrays; +SolidityParam.prototype.isDynamic = function () { + return this.value.length > 64; }; /** - * This method should be used to create bytearrays from param + * This method should be called to transform offset to bytes + * + * @method offsetAsBytes + * @returns {String} bytes representation of offset + */ +SolidityParam.prototype.offsetAsBytes = function () { + return !this.isDynamic() ? '' : utils.padLeft(utils.toTwosComplement(this.offset).toString(16), 64); +}; + +/** + * This method should be called to get static part of param + * + * @method staticPart + * @returns {String} offset if it is a dynamic param, otherwise value + */ +SolidityParam.prototype.staticPart = function () { + if (!this.isDynamic()) { + return this.value; + } + return this.offsetAsBytes(); +}; + +/** + * This method should be called to get dynamic part of param + * + * @method dynamicPart + * @returns {String} returns a value if it is a dynamic param, otherwise empty string + */ +SolidityParam.prototype.dynamicPart = function () { + return this.isDynamic() ? this.value : ''; +}; + +/** + * This method should be called to encode param * * @method encode - * @return {String} encoded param(s) + * @returns {String} */ SolidityParam.prototype.encode = function () { - return this.prefix + this.value + this.suffix; + return this.staticPart() + this.dynamicPart(); }; /** - * This method should be used to shift first param from group of params + * This method should be called to encode array of params * - * @method shiftValue - * @return {SolidityParam} first value param + * @method encodeList + * @param {Array[SolidityParam]} params + * @returns {String} */ -SolidityParam.prototype.shiftValue = function () { - var value = this.value.slice(0, 64); - this.value = this.value.slice(64); - return new SolidityParam(value); +SolidityParam.encodeList = function (params) { + + // updating offsets + var totalOffset = params.length * 32; + var offsetParams = params.map(function (param) { + if (!param.isDynamic()) { + return param; + } + var offset = totalOffset; + totalOffset += param.dynamicPartLength(); + return param.withOffset(offset); + }); + + // encode everything! + return offsetParams.reduce(function (result, param) { + return result + param.dynamicPart(); + }, offsetParams.reduce(function (result, param) { + return result + param.staticPart(); + }, '')); }; /** - * This method should be used to first bytes param from group of params + * This method should be used to decode plain (static) solidity param at given index * - * @method shiftBytes - * @return {SolidityParam} first bytes param + * @method decodeParam + * @param {String} bytes + * @param {Number} index + * @returns {SolidityParam} */ -SolidityParam.prototype.shiftBytes = function () { - return this.shiftArray(1); +SolidityParam.decodeParam = function (bytes, index) { + index = index || 0; + return new SolidityParam(bytes.substr(index * 64, 64)); }; /** - * This method should be used to shift an array from group of params - * - * @method shiftArray - * @param {Number} size of an array to shift - * @return {SolidityParam} first array param + * This method should be called to get offset value from bytes at given index + * + * @method getOffset + * @param {String} bytes + * @param {Number} index + * @returns {Number} offset as number + */ +var getOffset = function (bytes, index) { + // we can do this cause offset is rather small + return parseInt('0x' + bytes.substr(index * 64, 64)); +}; + +/** + * This method should be called to decode solidity bytes param at given index + * + * @method decodeBytes + * @param {String} bytes + * @param {Number} index + * @returns {SolidityParam} + */ +SolidityParam.decodeBytes = function (bytes, index) { + index = index || 0; + //TODO add support for strings longer than 32 bytes + //var length = parseInt('0x' + bytes.substr(offset * 64, 64)); + + var offset = getOffset(bytes, index); + + // 2 * , cause we also parse length + return new SolidityParam(bytes.substr(offset * 2, 2 * 64)); +}; + +/** + * This method should be used to decode solidity array at given index + * + * @method decodeArray + * @param {String} bytes + * @param {Number} index + * @returns {SolidityParam} */ -SolidityParam.prototype.shiftArray = function (length) { - var prefix = this.prefix.slice(0, 64); - this.prefix = this.value.slice(64); - var suffix = this.suffix.slice(0, 64 * length); - this.suffix = this.suffix.slice(64 * length); - return new SolidityParam('', prefix, suffix); +SolidityParam.decodeArray = function (bytes, index) { + index = index || 0; + var offset = getOffset(bytes, index); + var length = parseInt('0x' + bytes.substr(offset * 2, 64)); + return new SolidityParam(bytes.substr(offset * 2, (length + 1) * 64)); }; module.exports = SolidityParam; -},{}],5:[function(require,module,exports){ +},{"../utils/utils":8}],5:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -828,6 +797,11 @@ var getConstructor = function (abi, numberOfArgs) { })[0]; }; +//var getSupremeType = function (type) { + //return type.substr(0, type.indexOf('[')) + ']'; +//}; + + module.exports = { getConstructor: getConstructor }; @@ -1394,7 +1368,7 @@ module.exports = { },{"bignumber.js":"bignumber.js"}],9:[function(require,module,exports){ module.exports={ - "version": "0.3.3" + "version": "0.3.6" } },{}],10:[function(require,module,exports){ @@ -1796,7 +1770,7 @@ module.exports = { /** * Web3 - * + * * @module web3 */ @@ -1850,16 +1824,16 @@ var uncleCountCall = function (args) { /// @returns an array of objects describing web3.eth api methods var getBalance = new Method({ - name: 'getBalance', - call: 'eth_getBalance', + name: 'getBalance', + call: 'eth_getBalance', params: 2, inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter], outputFormatter: formatters.outputBigNumberFormatter }); var getStorageAt = new Method({ - name: 'getStorageAt', - call: 'eth_getStorageAt', + name: 'getStorageAt', + call: 'eth_getStorageAt', params: 3, inputFormatter: [null, utils.toHex, formatters.inputDefaultBlockNumberFormatter] }); @@ -1872,7 +1846,7 @@ var getCode = new Method({ }); var getBlock = new Method({ - name: 'getBlock', + name: 'getBlock', call: blockCall, params: 2, inputFormatter: [formatters.inputBlockNumberFormatter, function (val) { return !!val; }], @@ -1997,6 +1971,11 @@ var properties = [ name: 'mining', getter: 'eth_mining' }), + new Property({ + name: 'hashrate', + getter: 'eth_hashrate', + outputFormatter: utils.toDecimal + }), new Property({ name: 'gasPrice', getter: 'eth_gasPrice', @@ -2118,7 +2097,7 @@ SolidityEvent.prototype.encode = function (indexed, options) { ['fromBlock', 'toBlock'].filter(function (f) { return options[f] !== undefined; }).forEach(function (f) { - result[f] = utils.toHex(options[f]); + result[f] = formatters.inputBlockNumberFormatter(options[f]); }); result.topics = []; @@ -2447,7 +2426,7 @@ var inputTransactionFormatter = function (options){ delete options.code; } - ['gasPrice', 'gas', 'value'].filter(function (key) { + ['gasPrice', 'gas', 'value', 'nonce'].filter(function (key) { return options[key] !== undefined; }).forEach(function(key){ options[key] = utils.fromDecimal(options[key]); @@ -2796,15 +2775,32 @@ HttpProvider.prototype.send = function (payload) { //if (request.status !== 200) { //return; //} - return JSON.parse(request.responseText); + + var result = request.responseText; + + try { + result = JSON.parse(result); + } catch(e) { + throw errors.InvalidResponse(result); + } + + return result; }; HttpProvider.prototype.sendAsync = function (payload, callback) { var request = new XMLHttpRequest(); request.onreadystatechange = function() { if (request.readyState === 4) { - // TODO: handle the error properly here!!! - callback(null, JSON.parse(request.responseText)); + var result = request.responseText; + var error = null; + + try { + result = JSON.parse(result); + } catch(e) { + error = errors.InvalidResponse(result); + } + + callback(error, result); } }; diff --git a/libjsqrc/ethereumjs/dist/web3.js.map b/libjsqrc/ethereumjs/dist/web3.js.map index c989052e7..4efb07df1 100644 --- a/libjsqrc/ethereumjs/dist/web3.js.map +++ b/libjsqrc/ethereumjs/dist/web3.js.map @@ -34,30 +34,30 @@ "index.js" ], "names": [], - "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1dA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrGA;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3nFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", + "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1dA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5PA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrGA;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3nFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", "file": "generated.js", "sourceRoot": "", "sourcesContent": [ "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o.\n*/\n/** \n * @file abi.js\n * @author Marek Kotewicz \n * @author Gav Wood \n * @date 2014\n */\n\nvar utils = require('../utils/utils');\nvar coder = require('./coder');\nvar solUtils = require('./utils');\n\n/**\n * Formats input params to bytes\n *\n * @method formatInput\n * @param {Array} abi inputs of method\n * @param {Array} params that will be formatted to bytes\n * @returns bytes representation of input params\n */\nvar formatInput = function (inputs, params) {\n var i = inputs.map(function (input) {\n return input.type;\n });\n return coder.encodeParams(i, params);\n};\n\n/** \n * Formats output bytes back to param list\n *\n * @method formatOutput\n * @param {Array} abi outputs of method\n * @param {String} bytes represention of output\n * @returns {Array} output params\n */\nvar formatOutput = function (outs, bytes) {\n var o = outs.map(function (out) {\n return out.type;\n });\n \n return coder.decodeParams(o, bytes); \n};\n\n/**\n * Should be called to create input parser for contract with given abi\n *\n * @method inputParser\n * @param {Array} contract abi\n * @returns {Object} input parser object for given json abi\n * TODO: refactor creating the parser, do not double logic from contract\n */\nvar inputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n var displayName = utils.extractDisplayName(method.name);\n var typeName = utils.extractTypeName(method.name);\n\n var impl = function () {\n var params = Array.prototype.slice.call(arguments);\n return formatInput(method.inputs, params);\n };\n\n if (parser[displayName] === undefined) {\n parser[displayName] = impl;\n }\n\n parser[displayName][typeName] = impl;\n });\n\n return parser;\n};\n\n/**\n * Should be called to create output parser for contract with given abi\n *\n * @method outputParser\n * @param {Array} contract abi\n * @returns {Object} output parser for given json abi\n */\nvar outputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n\n var displayName = utils.extractDisplayName(method.name);\n var typeName = utils.extractTypeName(method.name);\n\n var impl = function (output) {\n return formatOutput(method.outputs, output);\n };\n\n if (parser[displayName] === undefined) {\n parser[displayName] = impl;\n }\n\n parser[displayName][typeName] = impl;\n });\n\n return parser;\n};\n\nvar formatConstructorParams = function (abi, params) {\n var constructor = solUtils.getConstructor(abi, params.length);\n if (!constructor) {\n if (params.length > 0) {\n console.warn(\"didn't found matching constructor, using default one\");\n }\n return '';\n }\n return formatInput(constructor.inputs, params);\n};\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n formatInput: formatInput,\n formatOutput: formatOutput,\n formatConstructorParams: formatConstructorParams\n};\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file coder.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar BigNumber = require('bignumber.js');\nvar utils = require('../utils/utils');\nvar f = require('./formatters');\nvar SolidityParam = require('./param');\n\n/**\n * Should be used to check if a type is an array type\n *\n * @method isArrayType\n * @param {String} type\n * @return {Bool} true is the type is an array, otherwise false\n */\nvar isArrayType = function (type) {\n return type.slice(-2) === '[]';\n};\n\n/**\n * SolidityType prototype is used to encode/decode solidity params of certain type\n */\nvar SolidityType = function (config) {\n this._name = config.name;\n this._match = config.match;\n this._mode = config.mode;\n this._inputFormatter = config.inputFormatter;\n this._outputFormatter = config.outputFormatter;\n};\n\n/**\n * Should be used to determine if this SolidityType do match given type\n *\n * @method isType\n * @param {String} name\n * @return {Bool} true if type match this SolidityType, otherwise false\n */\nSolidityType.prototype.isType = function (name) {\n if (this._match === 'strict') {\n return this._name === name || (name.indexOf(this._name) === 0 && name.slice(this._name.length) === '[]');\n } else if (this._match === 'prefix') {\n // TODO better type detection!\n return name.indexOf(this._name) === 0;\n }\n};\n\n/**\n * Should be used to transform plain param to SolidityParam object\n *\n * @method formatInput\n * @param {Object} param - plain object, or an array of objects\n * @param {Bool} arrayType - true if a param should be encoded as an array\n * @return {SolidityParam} encoded param wrapped in SolidityParam object \n */\nSolidityType.prototype.formatInput = function (param, arrayType) {\n if (utils.isArray(param) && arrayType) { // TODO: should fail if this two are not the same\n var self = this;\n return param.map(function (p) {\n return self._inputFormatter(p);\n }).reduce(function (acc, current) {\n acc.appendArrayElement(current);\n return acc;\n }, new SolidityParam('', f.formatInputInt(param.length).value));\n } \n return this._inputFormatter(param);\n};\n\n/**\n * Should be used to transoform SolidityParam to plain param\n *\n * @method formatOutput\n * @param {SolidityParam} byteArray\n * @param {Bool} arrayType - true if a param should be decoded as an array\n * @return {Object} plain decoded param\n */\nSolidityType.prototype.formatOutput = function (param, arrayType) {\n if (arrayType) {\n // let's assume, that we solidity will never return long arrays :P \n var result = [];\n var length = new BigNumber(param.prefix, 16);\n for (var i = 0; i < length * 64; i += 64) {\n result.push(this._outputFormatter(new SolidityParam(param.suffix.slice(i, i + 64))));\n }\n return result;\n }\n return this._outputFormatter(param);\n};\n\n/**\n * Should be used to check if a type is variadic\n *\n * @method isVariadicType\n * @param {String} type\n * @returns {Bool} true if the type is variadic\n */\nSolidityType.prototype.isVariadicType = function (type) {\n return isArrayType(type) || this._mode === 'bytes';\n};\n\n/**\n * Should be used to shift param from params group\n *\n * @method shiftParam\n * @param {String} type\n * @returns {SolidityParam} shifted param\n */\nSolidityType.prototype.shiftParam = function (type, param) {\n if (this._mode === 'bytes') {\n return param.shiftBytes();\n } else if (isArrayType(type)) {\n var length = new BigNumber(param.prefix.slice(0, 64), 16);\n return param.shiftArray(length);\n }\n return param.shiftValue();\n};\n\n/**\n * SolidityCoder prototype should be used to encode/decode solidity params of any type\n */\nvar SolidityCoder = function (types) {\n this._types = types;\n};\n\n/**\n * This method should be used to transform type to SolidityType\n *\n * @method _requireType\n * @param {String} type\n * @returns {SolidityType} \n * @throws {Error} throws if no matching type is found\n */\nSolidityCoder.prototype._requireType = function (type) {\n var solidityType = this._types.filter(function (t) {\n return t.isType(type);\n })[0];\n\n if (!solidityType) {\n throw Error('invalid solidity type!: ' + type);\n }\n\n return solidityType;\n};\n\n/**\n * Should be used to transform plain bytes to SolidityParam object\n *\n * @method _bytesToParam\n * @param {Array} types of params\n * @param {String} bytes to be transformed to SolidityParam\n * @return {SolidityParam} SolidityParam for this group of params\n */\nSolidityCoder.prototype._bytesToParam = function (types, bytes) {\n var self = this;\n var prefixTypes = types.reduce(function (acc, type) {\n return self._requireType(type).isVariadicType(type) ? acc + 1 : acc;\n }, 0);\n var valueTypes = types.length - prefixTypes;\n\n var prefix = bytes.slice(0, prefixTypes * 64);\n bytes = bytes.slice(prefixTypes * 64);\n var value = bytes.slice(0, valueTypes * 64);\n var suffix = bytes.slice(valueTypes * 64);\n return new SolidityParam(value, prefix, suffix); \n};\n\n/**\n * Should be used to transform plain param of given type to SolidityParam\n *\n * @method _formatInput\n * @param {String} type of param\n * @param {Object} plain param\n * @return {SolidityParam}\n */\nSolidityCoder.prototype._formatInput = function (type, param) {\n return this._requireType(type).formatInput(param, isArrayType(type));\n};\n\n/**\n * Should be used to encode plain param\n *\n * @method encodeParam\n * @param {String} type\n * @param {Object} plain param\n * @return {String} encoded plain param\n */\nSolidityCoder.prototype.encodeParam = function (type, param) {\n return this._formatInput(type, param).encode();\n};\n\n/**\n * Should be used to encode list of params\n *\n * @method encodeParams\n * @param {Array} types\n * @param {Array} params\n * @return {String} encoded list of params\n */\nSolidityCoder.prototype.encodeParams = function (types, params) {\n var self = this;\n return types.map(function (type, index) {\n return self._formatInput(type, params[index]);\n }).reduce(function (acc, solidityParam) {\n acc.append(solidityParam);\n return acc;\n }, new SolidityParam()).encode();\n};\n\n/**\n * Should be used to transform SolidityParam to plain param\n *\n * @method _formatOutput\n * @param {String} type\n * @param {SolidityParam} param\n * @return {Object} plain param\n */\nSolidityCoder.prototype._formatOutput = function (type, param) {\n return this._requireType(type).formatOutput(param, isArrayType(type));\n};\n\n/**\n * Should be used to decode bytes to plain param\n *\n * @method decodeParam\n * @param {String} type\n * @param {String} bytes\n * @return {Object} plain param\n */\nSolidityCoder.prototype.decodeParam = function (type, bytes) {\n return this._formatOutput(type, this._bytesToParam([type], bytes));\n};\n\n/**\n * Should be used to decode list of params\n *\n * @method decodeParam\n * @param {Array} types\n * @param {String} bytes\n * @return {Array} array of plain params\n */\nSolidityCoder.prototype.decodeParams = function (types, bytes) {\n var self = this;\n var param = this._bytesToParam(types, bytes);\n return types.map(function (type) {\n var solidityType = self._requireType(type);\n var p = solidityType.shiftParam(type, param);\n return solidityType.formatOutput(p, isArrayType(type));\n });\n};\n\nvar coder = new SolidityCoder([\n new SolidityType({\n name: 'address',\n match: 'strict',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputAddress\n }),\n new SolidityType({\n name: 'bool',\n match: 'strict',\n mode: 'value',\n inputFormatter: f.formatInputBool,\n outputFormatter: f.formatOutputBool\n }),\n new SolidityType({\n name: 'int',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputInt,\n }),\n new SolidityType({\n name: 'uint',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputUInt\n }),\n new SolidityType({\n name: 'bytes',\n match: 'strict',\n mode: 'bytes',\n inputFormatter: f.formatInputDynamicBytes,\n outputFormatter: f.formatOutputDynamicBytes\n }),\n new SolidityType({\n name: 'bytes',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputBytes,\n outputFormatter: f.formatOutputBytes\n }),\n new SolidityType({\n name: 'real',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputReal,\n outputFormatter: f.formatOutputReal\n }),\n new SolidityType({\n name: 'ureal',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputReal,\n outputFormatter: f.formatOutputUReal\n })\n]);\n\nmodule.exports = coder;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file formatters.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar BigNumber = require('bignumber.js');\nvar utils = require('../utils/utils');\nvar c = require('../utils/config');\nvar SolidityParam = require('./param');\n\n\n/**\n * Formats input value to byte representation of int\n * If value is negative, return it's two's complement\n * If the value is floating point, round it down\n *\n * @method formatInputInt\n * @param {String|Number|BigNumber} value that needs to be formatted\n * @returns {SolidityParam}\n */\nvar formatInputInt = function (value) {\n var padding = c.ETH_PADDING * 2;\n BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE);\n var result = utils.padLeft(utils.toTwosComplement(value).round().toString(16), padding);\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of string\n *\n * @method formatInputBytes\n * @param {String}\n * @returns {SolidityParam}\n */\nvar formatInputBytes = function (value) {\n var result = utils.fromAscii(value, c.ETH_PADDING).substr(2);\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of string\n *\n * @method formatInputDynamicBytes\n * @param {String}\n * @returns {SolidityParam}\n */\nvar formatInputDynamicBytes = function (value) {\n var result = utils.fromAscii(value, c.ETH_PADDING).substr(2);\n return new SolidityParam('', formatInputInt(value.length).value, result);\n};\n\n/**\n * Formats input value to byte representation of bool\n *\n * @method formatInputBool\n * @param {Boolean}\n * @returns {SolidityParam}\n */\nvar formatInputBool = function (value) {\n var result = '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of real\n * Values are multiplied by 2^m and encoded as integers\n *\n * @method formatInputReal\n * @param {String|Number|BigNumber}\n * @returns {SolidityParam}\n */\nvar formatInputReal = function (value) {\n return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128)));\n};\n\n/**\n * Check if input value is negative\n *\n * @method signedIsNegative\n * @param {String} value is hex format\n * @returns {Boolean} true if it is negative, otherwise false\n */\nvar signedIsNegative = function (value) {\n return (new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1)) === '1';\n};\n\n/**\n * Formats right-aligned output bytes to int\n *\n * @method formatOutputInt\n * @param {SolidityParam} param\n * @returns {BigNumber} right-aligned output bytes formatted to big number\n */\nvar formatOutputInt = function (param) {\n var value = param.value || \"0\";\n\n // check if it's negative number\n // it it is, return two's complement\n if (signedIsNegative(value)) {\n return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1);\n }\n return new BigNumber(value, 16);\n};\n\n/**\n * Formats right-aligned output bytes to uint\n *\n * @method formatOutputUInt\n * @param {SolidityParam}\n * @returns {BigNumeber} right-aligned output bytes formatted to uint\n */\nvar formatOutputUInt = function (param) {\n var value = param.value || \"0\";\n return new BigNumber(value, 16);\n};\n\n/**\n * Formats right-aligned output bytes to real\n *\n * @method formatOutputReal\n * @param {SolidityParam}\n * @returns {BigNumber} input bytes formatted to real\n */\nvar formatOutputReal = function (param) {\n return formatOutputInt(param).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/**\n * Formats right-aligned output bytes to ureal\n *\n * @method formatOutputUReal\n * @param {SolidityParam}\n * @returns {BigNumber} input bytes formatted to ureal\n */\nvar formatOutputUReal = function (param) {\n return formatOutputUInt(param).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/**\n * Should be used to format output bool\n *\n * @method formatOutputBool\n * @param {SolidityParam}\n * @returns {Boolean} right-aligned input bytes formatted to bool\n */\nvar formatOutputBool = function (param) {\n return param.value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;\n};\n\n/**\n * Should be used to format output string\n *\n * @method formatOutputBytes\n * @param {SolidityParam} left-aligned hex representation of string\n * @returns {String} ascii string\n */\nvar formatOutputBytes = function (param) {\n // length might also be important!\n return utils.toAscii(param.value);\n};\n\n/**\n * Should be used to format output string\n *\n * @method formatOutputDynamicBytes\n * @param {SolidityParam} left-aligned hex representation of string\n * @returns {String} ascii string\n */\nvar formatOutputDynamicBytes = function (param) {\n // length might also be important!\n return utils.toAscii(param.suffix);\n};\n\n/**\n * Should be used to format output address\n *\n * @method formatOutputAddress\n * @param {SolidityParam} right-aligned input bytes\n * @returns {String} address\n */\nvar formatOutputAddress = function (param) {\n var value = param.value;\n return \"0x\" + value.slice(value.length - 40, value.length);\n};\n\nmodule.exports = {\n formatInputInt: formatInputInt,\n formatInputBytes: formatInputBytes,\n formatInputDynamicBytes: formatInputDynamicBytes,\n formatInputBool: formatInputBool,\n formatInputReal: formatInputReal,\n formatOutputInt: formatOutputInt,\n formatOutputUInt: formatOutputUInt,\n formatOutputReal: formatOutputReal,\n formatOutputUReal: formatOutputUReal,\n formatOutputBool: formatOutputBool,\n formatOutputBytes: formatOutputBytes,\n formatOutputDynamicBytes: formatOutputDynamicBytes,\n formatOutputAddress: formatOutputAddress\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file param.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\n/**\n * SolidityParam object prototype.\n * Should be used when encoding, decoding solidity bytes\n */\nvar SolidityParam = function (value, prefix, suffix) {\n this.prefix = prefix || '';\n this.value = value || '';\n this.suffix = suffix || '';\n};\n\n/**\n * This method should be used to encode two params one after another\n *\n * @method append\n * @param {SolidityParam} param that it appended after this\n */\nSolidityParam.prototype.append = function (param) {\n this.prefix += param.prefix;\n this.value += param.value;\n this.suffix += param.suffix;\n};\n\n/**\n * This method should be used to encode next param in an array\n *\n * @method appendArrayElement\n * @param {SolidityParam} param that is appended to an array\n */\nSolidityParam.prototype.appendArrayElement = function (param) {\n this.suffix += param.value;\n this.prefix += param.prefix;\n // TODO: suffix not supported = it's required for nested arrays;\n};\n\n/**\n * This method should be used to create bytearrays from param\n *\n * @method encode\n * @return {String} encoded param(s)\n */\nSolidityParam.prototype.encode = function () {\n return this.prefix + this.value + this.suffix;\n};\n\n/**\n * This method should be used to shift first param from group of params\n *\n * @method shiftValue\n * @return {SolidityParam} first value param\n */\nSolidityParam.prototype.shiftValue = function () {\n var value = this.value.slice(0, 64);\n this.value = this.value.slice(64);\n return new SolidityParam(value);\n};\n\n/**\n * This method should be used to first bytes param from group of params\n *\n * @method shiftBytes\n * @return {SolidityParam} first bytes param\n */\nSolidityParam.prototype.shiftBytes = function () {\n return this.shiftArray(1); \n};\n\n/**\n * This method should be used to shift an array from group of params \n * \n * @method shiftArray\n * @param {Number} size of an array to shift\n * @return {SolidityParam} first array param\n */\nSolidityParam.prototype.shiftArray = function (length) {\n var prefix = this.prefix.slice(0, 64);\n this.prefix = this.value.slice(64);\n var suffix = this.suffix.slice(0, 64 * length);\n this.suffix = this.suffix.slice(64 * length);\n return new SolidityParam('', prefix, suffix);\n};\n\nmodule.exports = SolidityParam;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/**\n * @file utils.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\n/**\n * Returns the contstructor with matching number of arguments\n *\n * @method getConstructor\n * @param {Array} abi\n * @param {Number} numberOfArgs\n * @returns {Object} constructor function abi\n */\nvar getConstructor = function (abi, numberOfArgs) {\n return abi.filter(function (f) {\n return f.type === 'constructor' && f.inputs.length === numberOfArgs;\n })[0];\n};\n\nmodule.exports = {\n getConstructor: getConstructor\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file abi.js\n * @author Marek Kotewicz \n * @author Gav Wood \n * @date 2014\n */\n\nvar coder = require('./coder');\nvar utils = require('./utils');\n\nvar formatConstructorParams = function (abi, params) {\n var constructor = utils.getConstructor(abi, params.length);\n if (!constructor) {\n if (params.length > 0) {\n console.warn(\"didn't found matching constructor, using default one\");\n }\n return '';\n }\n\n return coder.encodeParams(constructor.inputs.map(function (input) {\n return input.type;\n }), params);\n};\n\nmodule.exports = {\n formatConstructorParams: formatConstructorParams\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file coder.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar BigNumber = require('bignumber.js');\nvar utils = require('../utils/utils');\nvar f = require('./formatters');\nvar SolidityParam = require('./param');\n\n/**\n * Should be used to check if a type is an array type\n *\n * @method isArrayType\n * @param {String} type\n * @return {Bool} true is the type is an array, otherwise false\n */\nvar isArrayType = function (type) {\n return type.slice(-2) === '[]';\n};\n\n/**\n * SolidityType prototype is used to encode/decode solidity params of certain type\n */\nvar SolidityType = function (config) {\n this._name = config.name;\n this._match = config.match;\n this._mode = config.mode;\n this._inputFormatter = config.inputFormatter;\n this._outputFormatter = config.outputFormatter;\n};\n\n/**\n * Should be used to determine if this SolidityType do match given type\n *\n * @method isType\n * @param {String} name\n * @return {Bool} true if type match this SolidityType, otherwise false\n */\nSolidityType.prototype.isType = function (name) {\n if (this._match === 'strict') {\n return this._name === name || (name.indexOf(this._name) === 0 && name.slice(this._name.length) === '[]');\n } else if (this._match === 'prefix') {\n // TODO better type detection!\n return name.indexOf(this._name) === 0;\n }\n};\n\n/**\n * Should be used to transform plain param to SolidityParam object\n *\n * @method formatInput\n * @param {Object} param - plain object, or an array of objects\n * @param {Bool} arrayType - true if a param should be encoded as an array\n * @return {SolidityParam} encoded param wrapped in SolidityParam object \n */\nSolidityType.prototype.formatInput = function (param, arrayType) {\n if (utils.isArray(param) && arrayType) { // TODO: should fail if this two are not the same\n var self = this;\n return param.map(function (p) {\n return self._inputFormatter(p);\n }).reduce(function (acc, current) {\n return acc.combine(current);\n }, f.formatInputInt(param.length)).withOffset(32);\n } \n return this._inputFormatter(param);\n};\n\n/**\n * Should be used to transoform SolidityParam to plain param\n *\n * @method formatOutput\n * @param {SolidityParam} byteArray\n * @param {Bool} arrayType - true if a param should be decoded as an array\n * @return {Object} plain decoded param\n */\nSolidityType.prototype.formatOutput = function (param, arrayType) {\n if (arrayType) {\n // let's assume, that we solidity will never return long arrays :P \n var result = [];\n var length = new BigNumber(param.dynamicPart().slice(0, 64), 16);\n for (var i = 0; i < length * 64; i += 64) {\n result.push(this._outputFormatter(new SolidityParam(param.dynamicPart().substr(i + 64, 64))));\n }\n return result;\n }\n return this._outputFormatter(param);\n};\n\n/**\n * Should be used to slice single param from bytes\n *\n * @method sliceParam\n * @param {String} bytes\n * @param {Number} index of param to slice\n * @param {String} type\n * @returns {SolidityParam} param\n */\nSolidityType.prototype.sliceParam = function (bytes, index, type) {\n if (this._mode === 'bytes') {\n return SolidityParam.decodeBytes(bytes, index);\n } else if (isArrayType(type)) {\n return SolidityParam.decodeArray(bytes, index);\n }\n return SolidityParam.decodeParam(bytes, index);\n};\n\n/**\n * SolidityCoder prototype should be used to encode/decode solidity params of any type\n */\nvar SolidityCoder = function (types) {\n this._types = types;\n};\n\n/**\n * This method should be used to transform type to SolidityType\n *\n * @method _requireType\n * @param {String} type\n * @returns {SolidityType} \n * @throws {Error} throws if no matching type is found\n */\nSolidityCoder.prototype._requireType = function (type) {\n var solidityType = this._types.filter(function (t) {\n return t.isType(type);\n })[0];\n\n if (!solidityType) {\n throw Error('invalid solidity type!: ' + type);\n }\n\n return solidityType;\n};\n\n/**\n * Should be used to transform plain param of given type to SolidityParam\n *\n * @method _formatInput\n * @param {String} type of param\n * @param {Object} plain param\n * @return {SolidityParam}\n */\nSolidityCoder.prototype._formatInput = function (type, param) {\n return this._requireType(type).formatInput(param, isArrayType(type));\n};\n\n/**\n * Should be used to encode plain param\n *\n * @method encodeParam\n * @param {String} type\n * @param {Object} plain param\n * @return {String} encoded plain param\n */\nSolidityCoder.prototype.encodeParam = function (type, param) {\n return this._formatInput(type, param).encode();\n};\n\n/**\n * Should be used to encode list of params\n *\n * @method encodeParams\n * @param {Array} types\n * @param {Array} params\n * @return {String} encoded list of params\n */\nSolidityCoder.prototype.encodeParams = function (types, params) {\n var self = this;\n var solidityParams = types.map(function (type, index) {\n return self._formatInput(type, params[index]);\n });\n\n return SolidityParam.encodeList(solidityParams);\n};\n\n/**\n * Should be used to decode bytes to plain param\n *\n * @method decodeParam\n * @param {String} type\n * @param {String} bytes\n * @return {Object} plain param\n */\nSolidityCoder.prototype.decodeParam = function (type, bytes) {\n return this.decodeParams([type], bytes)[0];\n};\n\n/**\n * Should be used to decode list of params\n *\n * @method decodeParam\n * @param {Array} types\n * @param {String} bytes\n * @return {Array} array of plain params\n */\nSolidityCoder.prototype.decodeParams = function (types, bytes) {\n var self = this;\n return types.map(function (type, index) {\n var solidityType = self._requireType(type);\n var p = solidityType.sliceParam(bytes, index, type);\n return solidityType.formatOutput(p, isArrayType(type));\n });\n};\n\nvar coder = new SolidityCoder([\n new SolidityType({\n name: 'address',\n match: 'strict',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputAddress\n }),\n new SolidityType({\n name: 'bool',\n match: 'strict',\n mode: 'value',\n inputFormatter: f.formatInputBool,\n outputFormatter: f.formatOutputBool\n }),\n new SolidityType({\n name: 'int',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputInt,\n }),\n new SolidityType({\n name: 'uint',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputInt,\n outputFormatter: f.formatOutputUInt\n }),\n new SolidityType({\n name: 'bytes',\n match: 'strict',\n mode: 'bytes',\n inputFormatter: f.formatInputDynamicBytes,\n outputFormatter: f.formatOutputDynamicBytes\n }),\n new SolidityType({\n name: 'bytes',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputBytes,\n outputFormatter: f.formatOutputBytes\n }),\n new SolidityType({\n name: 'real',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputReal,\n outputFormatter: f.formatOutputReal\n }),\n new SolidityType({\n name: 'ureal',\n match: 'prefix',\n mode: 'value',\n inputFormatter: f.formatInputReal,\n outputFormatter: f.formatOutputUReal\n })\n]);\n\nmodule.exports = coder;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file formatters.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar BigNumber = require('bignumber.js');\nvar utils = require('../utils/utils');\nvar c = require('../utils/config');\nvar SolidityParam = require('./param');\n\n\n/**\n * Formats input value to byte representation of int\n * If value is negative, return it's two's complement\n * If the value is floating point, round it down\n *\n * @method formatInputInt\n * @param {String|Number|BigNumber} value that needs to be formatted\n * @returns {SolidityParam}\n */\nvar formatInputInt = function (value) {\n var padding = c.ETH_PADDING * 2;\n BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE);\n var result = utils.padLeft(utils.toTwosComplement(value).round().toString(16), padding);\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of string\n *\n * @method formatInputBytes\n * @param {String}\n * @returns {SolidityParam}\n */\nvar formatInputBytes = function (value) {\n var result = utils.fromAscii(value, c.ETH_PADDING).substr(2);\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of string\n *\n * @method formatInputDynamicBytes\n * @param {String}\n * @returns {SolidityParam}\n */\nvar formatInputDynamicBytes = function (value) {\n var result = utils.fromAscii(value, c.ETH_PADDING).substr(2);\n return new SolidityParam(formatInputInt(value.length).value + result, 32);\n};\n\n/**\n * Formats input value to byte representation of bool\n *\n * @method formatInputBool\n * @param {Boolean}\n * @returns {SolidityParam}\n */\nvar formatInputBool = function (value) {\n var result = '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');\n return new SolidityParam(result);\n};\n\n/**\n * Formats input value to byte representation of real\n * Values are multiplied by 2^m and encoded as integers\n *\n * @method formatInputReal\n * @param {String|Number|BigNumber}\n * @returns {SolidityParam}\n */\nvar formatInputReal = function (value) {\n return formatInputInt(new BigNumber(value).times(new BigNumber(2).pow(128)));\n};\n\n/**\n * Check if input value is negative\n *\n * @method signedIsNegative\n * @param {String} value is hex format\n * @returns {Boolean} true if it is negative, otherwise false\n */\nvar signedIsNegative = function (value) {\n return (new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1)) === '1';\n};\n\n/**\n * Formats right-aligned output bytes to int\n *\n * @method formatOutputInt\n * @param {SolidityParam} param\n * @returns {BigNumber} right-aligned output bytes formatted to big number\n */\nvar formatOutputInt = function (param) {\n var value = param.staticPart() || \"0\";\n\n // check if it's negative number\n // it it is, return two's complement\n if (signedIsNegative(value)) {\n return new BigNumber(value, 16).minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)).minus(1);\n }\n return new BigNumber(value, 16);\n};\n\n/**\n * Formats right-aligned output bytes to uint\n *\n * @method formatOutputUInt\n * @param {SolidityParam}\n * @returns {BigNumeber} right-aligned output bytes formatted to uint\n */\nvar formatOutputUInt = function (param) {\n var value = param.staticPart() || \"0\";\n return new BigNumber(value, 16);\n};\n\n/**\n * Formats right-aligned output bytes to real\n *\n * @method formatOutputReal\n * @param {SolidityParam}\n * @returns {BigNumber} input bytes formatted to real\n */\nvar formatOutputReal = function (param) {\n return formatOutputInt(param).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/**\n * Formats right-aligned output bytes to ureal\n *\n * @method formatOutputUReal\n * @param {SolidityParam}\n * @returns {BigNumber} input bytes formatted to ureal\n */\nvar formatOutputUReal = function (param) {\n return formatOutputUInt(param).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/**\n * Should be used to format output bool\n *\n * @method formatOutputBool\n * @param {SolidityParam}\n * @returns {Boolean} right-aligned input bytes formatted to bool\n */\nvar formatOutputBool = function (param) {\n return param.staticPart() === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;\n};\n\n/**\n * Should be used to format output string\n *\n * @method formatOutputBytes\n * @param {SolidityParam} left-aligned hex representation of string\n * @returns {String} ascii string\n */\nvar formatOutputBytes = function (param) {\n // length might also be important!\n return utils.toAscii(param.staticPart());\n};\n\n/**\n * Should be used to format output string\n *\n * @method formatOutputDynamicBytes\n * @param {SolidityParam} left-aligned hex representation of string\n * @returns {String} ascii string\n */\nvar formatOutputDynamicBytes = function (param) {\n // length might also be important!\n return utils.toAscii(param.dynamicPart().slice(64));\n};\n\n/**\n * Should be used to format output address\n *\n * @method formatOutputAddress\n * @param {SolidityParam} right-aligned input bytes\n * @returns {String} address\n */\nvar formatOutputAddress = function (param) {\n var value = param.staticPart();\n return \"0x\" + value.slice(value.length - 40, value.length);\n};\n\nmodule.exports = {\n formatInputInt: formatInputInt,\n formatInputBytes: formatInputBytes,\n formatInputDynamicBytes: formatInputDynamicBytes,\n formatInputBool: formatInputBool,\n formatInputReal: formatInputReal,\n formatOutputInt: formatOutputInt,\n formatOutputUInt: formatOutputUInt,\n formatOutputReal: formatOutputReal,\n formatOutputUReal: formatOutputUReal,\n formatOutputBool: formatOutputBool,\n formatOutputBytes: formatOutputBytes,\n formatOutputDynamicBytes: formatOutputDynamicBytes,\n formatOutputAddress: formatOutputAddress\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file param.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar utils = require('../utils/utils');\n\n/**\n * SolidityParam object prototype.\n * Should be used when encoding, decoding solidity bytes\n */\nvar SolidityParam = function (value, offset) {\n this.value = value || '';\n this.offset = offset; // offset in bytes\n};\n\n/**\n * This method should be used to get length of params's dynamic part\n * \n * @method dynamicPartLength\n * @returns {Number} length of dynamic part (in bytes)\n */\nSolidityParam.prototype.dynamicPartLength = function () {\n return this.dynamicPart().length / 2;\n};\n\n/**\n * This method should be used to create copy of solidity param with different offset\n *\n * @method withOffset\n * @param {Number} offset length in bytes\n * @returns {SolidityParam} new solidity param with applied offset\n */\nSolidityParam.prototype.withOffset = function (offset) {\n return new SolidityParam(this.value, offset);\n};\n\n/**\n * This method should be used to combine solidity params together\n * eg. when appending an array\n *\n * @method combine\n * @param {SolidityParam} param with which we should combine\n * @param {SolidityParam} result of combination\n */\nSolidityParam.prototype.combine = function (param) {\n return new SolidityParam(this.value + param.value); \n};\n\n/**\n * This method should be called to check if param has dynamic size.\n * If it has, it returns true, otherwise false\n *\n * @method isDynamic\n * @returns {Boolean}\n */\nSolidityParam.prototype.isDynamic = function () {\n return this.value.length > 64;\n};\n\n/**\n * This method should be called to transform offset to bytes\n *\n * @method offsetAsBytes\n * @returns {String} bytes representation of offset\n */\nSolidityParam.prototype.offsetAsBytes = function () {\n return !this.isDynamic() ? '' : utils.padLeft(utils.toTwosComplement(this.offset).toString(16), 64);\n};\n\n/**\n * This method should be called to get static part of param\n *\n * @method staticPart\n * @returns {String} offset if it is a dynamic param, otherwise value\n */\nSolidityParam.prototype.staticPart = function () {\n if (!this.isDynamic()) {\n return this.value; \n } \n return this.offsetAsBytes();\n};\n\n/**\n * This method should be called to get dynamic part of param\n *\n * @method dynamicPart\n * @returns {String} returns a value if it is a dynamic param, otherwise empty string\n */\nSolidityParam.prototype.dynamicPart = function () {\n return this.isDynamic() ? this.value : '';\n};\n\n/**\n * This method should be called to encode param\n *\n * @method encode\n * @returns {String}\n */\nSolidityParam.prototype.encode = function () {\n return this.staticPart() + this.dynamicPart();\n};\n\n/**\n * This method should be called to encode array of params\n *\n * @method encodeList\n * @param {Array[SolidityParam]} params\n * @returns {String}\n */\nSolidityParam.encodeList = function (params) {\n \n // updating offsets\n var totalOffset = params.length * 32;\n var offsetParams = params.map(function (param) {\n if (!param.isDynamic()) {\n return param;\n }\n var offset = totalOffset;\n totalOffset += param.dynamicPartLength();\n return param.withOffset(offset);\n });\n\n // encode everything!\n return offsetParams.reduce(function (result, param) {\n return result + param.dynamicPart();\n }, offsetParams.reduce(function (result, param) {\n return result + param.staticPart();\n }, ''));\n};\n\n/**\n * This method should be used to decode plain (static) solidity param at given index\n *\n * @method decodeParam\n * @param {String} bytes\n * @param {Number} index\n * @returns {SolidityParam}\n */\nSolidityParam.decodeParam = function (bytes, index) {\n index = index || 0;\n return new SolidityParam(bytes.substr(index * 64, 64)); \n};\n\n/**\n * This method should be called to get offset value from bytes at given index\n *\n * @method getOffset\n * @param {String} bytes\n * @param {Number} index\n * @returns {Number} offset as number\n */\nvar getOffset = function (bytes, index) {\n // we can do this cause offset is rather small\n return parseInt('0x' + bytes.substr(index * 64, 64));\n};\n\n/**\n * This method should be called to decode solidity bytes param at given index\n *\n * @method decodeBytes\n * @param {String} bytes\n * @param {Number} index\n * @returns {SolidityParam}\n */\nSolidityParam.decodeBytes = function (bytes, index) {\n index = index || 0;\n //TODO add support for strings longer than 32 bytes\n //var length = parseInt('0x' + bytes.substr(offset * 64, 64));\n\n var offset = getOffset(bytes, index);\n\n // 2 * , cause we also parse length\n return new SolidityParam(bytes.substr(offset * 2, 2 * 64));\n};\n\n/**\n * This method should be used to decode solidity array at given index\n *\n * @method decodeArray\n * @param {String} bytes\n * @param {Number} index\n * @returns {SolidityParam}\n */\nSolidityParam.decodeArray = function (bytes, index) {\n index = index || 0;\n var offset = getOffset(bytes, index);\n var length = parseInt('0x' + bytes.substr(offset * 2, 64));\n return new SolidityParam(bytes.substr(offset * 2, (length + 1) * 64));\n};\n\nmodule.exports = SolidityParam;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/**\n * @file utils.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\n/**\n * Returns the contstructor with matching number of arguments\n *\n * @method getConstructor\n * @param {Array} abi\n * @param {Number} numberOfArgs\n * @returns {Object} constructor function abi\n */\nvar getConstructor = function (abi, numberOfArgs) {\n return abi.filter(function (f) {\n return f.type === 'constructor' && f.inputs.length === numberOfArgs;\n })[0];\n};\n\n//var getSupremeType = function (type) {\n //return type.substr(0, type.indexOf('[')) + ']';\n//};\n\n\nmodule.exports = {\n getConstructor: getConstructor\n};\n\n", "'use strict';\n\n// go env doesn't have and need XMLHttpRequest\nif (typeof XMLHttpRequest === 'undefined') {\n exports.XMLHttpRequest = {};\n} else {\n exports.XMLHttpRequest = XMLHttpRequest; // jshint ignore:line\n}\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file config.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\n/**\n * Utils\n * \n * @module utils\n */\n\n/**\n * Utility functions\n * \n * @class [utils] config\n * @constructor\n */\n\n/// required to define ETH_BIGNUMBER_ROUNDING_MODE\nvar BigNumber = require('bignumber.js');\n\nvar ETH_UNITS = [ \n 'wei', \n 'Kwei', \n 'Mwei', \n 'Gwei', \n 'szabo', \n 'finney', \n 'ether', \n 'grand', \n 'Mether', \n 'Gether', \n 'Tether', \n 'Pether', \n 'Eether', \n 'Zether', \n 'Yether', \n 'Nether', \n 'Dether', \n 'Vether', \n 'Uether' \n];\n\nmodule.exports = {\n ETH_PADDING: 32,\n ETH_SIGNATURE_LENGTH: 4,\n ETH_UNITS: ETH_UNITS,\n ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN },\n ETH_POLLING_TIMEOUT: 1000,\n defaultBlock: 'latest',\n defaultAccount: undefined\n};\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file utils.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\n/**\n * Utils\n * \n * @module utils\n */\n\n/**\n * Utility functions\n * \n * @class [utils] utils\n * @constructor\n */\n\nvar BigNumber = require('bignumber.js');\n\nvar unitMap = {\n 'wei': '1',\n 'kwei': '1000',\n 'ada': '1000',\n 'mwei': '1000000',\n 'babbage': '1000000',\n 'gwei': '1000000000',\n 'shannon': '1000000000',\n 'szabo': '1000000000000',\n 'finney': '1000000000000000',\n 'ether': '1000000000000000000',\n 'kether': '1000000000000000000000',\n 'grand': '1000000000000000000000',\n 'einstein': '1000000000000000000000',\n 'mether': '1000000000000000000000000',\n 'gether': '1000000000000000000000000000',\n 'tether': '1000000000000000000000000000000'\n};\n\n/**\n * Should be called to pad string to expected length\n *\n * @method padLeft\n * @param {String} string to be padded\n * @param {Number} characters that result string should have\n * @param {String} sign, by default 0\n * @returns {String} right aligned string\n */\nvar padLeft = function (string, chars, sign) {\n return new Array(chars - string.length + 1).join(sign ? sign : \"0\") + string;\n};\n\n/** \n * Should be called to get sting from it's hex representation\n *\n * @method toAscii\n * @param {String} string in hex\n * @returns {String} ascii string representation of hex value\n */\nvar toAscii = function(hex) {\n// Find termination\n var str = \"\";\n var i = 0, l = hex.length;\n if (hex.substring(0, 2) === '0x') {\n i = 2;\n }\n for (; i < l; i+=2) {\n var code = parseInt(hex.substr(i, 2), 16);\n if (code === 0) {\n break;\n }\n\n str += String.fromCharCode(code);\n }\n\n return str;\n};\n \n/**\n * Shold be called to get hex representation (prefixed by 0x) of ascii string \n *\n * @method toHexNative\n * @param {String} string\n * @returns {String} hex representation of input string\n */\nvar toHexNative = function(str) {\n var hex = \"\";\n for(var i = 0; i < str.length; i++) {\n var n = str.charCodeAt(i).toString(16);\n hex += n.length < 2 ? '0' + n : n;\n }\n\n return hex;\n};\n\n/**\n * Shold be called to get hex representation (prefixed by 0x) of ascii string \n *\n * @method fromAscii\n * @param {String} string\n * @param {Number} optional padding\n * @returns {String} hex representation of input string\n */\nvar fromAscii = function(str, pad) {\n pad = pad === undefined ? 0 : pad;\n var hex = toHexNative(str);\n while (hex.length < pad*2)\n hex += \"00\";\n return \"0x\" + hex;\n};\n\n/**\n * Should be used to create full function/event name from json abi\n *\n * @method transformToFullName\n * @param {Object} json-abi\n * @return {String} full fnction/event name\n */\nvar transformToFullName = function (json) {\n if (json.name.indexOf('(') !== -1) {\n return json.name;\n }\n\n var typeName = json.inputs.map(function(i){return i.type; }).join();\n return json.name + '(' + typeName + ')';\n};\n\n/**\n * Should be called to get display name of contract function\n * \n * @method extractDisplayName\n * @param {String} name of function/event\n * @returns {String} display name for function/event eg. multiply(uint256) -> multiply\n */\nvar extractDisplayName = function (name) {\n var length = name.indexOf('('); \n return length !== -1 ? name.substr(0, length) : name;\n};\n\n/// @returns overloaded part of function/event name\nvar extractTypeName = function (name) {\n /// TODO: make it invulnerable\n var length = name.indexOf('(');\n return length !== -1 ? name.substr(length + 1, name.length - 1 - (length + 1)).replace(' ', '') : \"\";\n};\n\n/**\n * Converts value to it's decimal representation in string\n *\n * @method toDecimal\n * @param {String|Number|BigNumber}\n * @return {String}\n */\nvar toDecimal = function (value) {\n return toBigNumber(value).toNumber();\n};\n\n/**\n * Converts value to it's hex representation\n *\n * @method fromDecimal\n * @param {String|Number|BigNumber}\n * @return {String}\n */\nvar fromDecimal = function (value) {\n var number = toBigNumber(value);\n var result = number.toString(16);\n\n return number.lessThan(0) ? '-0x' + result.substr(1) : '0x' + result;\n};\n\n/**\n * Auto converts any given value into it's hex representation.\n *\n * And even stringifys objects before.\n *\n * @method toHex\n * @param {String|Number|BigNumber|Object}\n * @return {String}\n */\nvar toHex = function (val) {\n /*jshint maxcomplexity:7 */\n\n if (isBoolean(val))\n return fromDecimal(+val);\n\n if (isBigNumber(val))\n return fromDecimal(val);\n\n if (isObject(val))\n return fromAscii(JSON.stringify(val));\n\n // if its a negative number, pass it through fromDecimal\n if (isString(val)) {\n if (val.indexOf('-0x') === 0)\n return fromDecimal(val);\n else if (!isFinite(val))\n return fromAscii(val);\n }\n\n return fromDecimal(val);\n};\n\n/**\n * Returns value of unit in Wei\n *\n * @method getValueOfUnit\n * @param {String} unit the unit to convert to, default ether\n * @returns {BigNumber} value of the unit (in Wei)\n * @throws error if the unit is not correct:w\n */\nvar getValueOfUnit = function (unit) {\n unit = unit ? unit.toLowerCase() : 'ether';\n var unitValue = unitMap[unit];\n if (unitValue === undefined) {\n throw new Error('This unit doesn\\'t exists, please use the one of the following units' + JSON.stringify(unitMap, null, 2));\n }\n return new BigNumber(unitValue, 10);\n};\n\n/**\n * Takes a number of wei and converts it to any other ether unit.\n *\n * Possible units are:\n * - kwei/ada\n * - mwei/babbage\n * - gwei/shannon\n * - szabo\n * - finney\n * - ether\n * - kether/grand/einstein\n * - mether\n * - gether\n * - tether\n *\n * @method fromWei\n * @param {Number|String} number can be a number, number string or a HEX of a decimal\n * @param {String} unit the unit to convert to, default ether\n * @return {String|Object} When given a BigNumber object it returns one as well, otherwise a number\n*/\nvar fromWei = function(number, unit) {\n var returnValue = toBigNumber(number).dividedBy(getValueOfUnit(unit));\n\n return isBigNumber(number) ? returnValue : returnValue.toString(10); \n};\n\n/**\n * Takes a number of a unit and converts it to wei.\n *\n * Possible units are:\n * - kwei/ada\n * - mwei/babbage\n * - gwei/shannon\n * - szabo\n * - finney\n * - ether\n * - kether/grand/einstein\n * - mether\n * - gether\n * - tether\n *\n * @method toWei\n * @param {Number|String|BigNumber} number can be a number, number string or a HEX of a decimal\n * @param {String} unit the unit to convert from, default ether\n * @return {String|Object} When given a BigNumber object it returns one as well, otherwise a number\n*/\nvar toWei = function(number, unit) {\n var returnValue = toBigNumber(number).times(getValueOfUnit(unit));\n\n return isBigNumber(number) ? returnValue : returnValue.toString(10); \n};\n\n/**\n * Takes an input and transforms it into an bignumber\n *\n * @method toBigNumber\n * @param {Number|String|BigNumber} a number, string, HEX string or BigNumber\n * @return {BigNumber} BigNumber\n*/\nvar toBigNumber = function(number) {\n /*jshint maxcomplexity:5 */\n number = number || 0;\n if (isBigNumber(number))\n return number;\n\n if (isString(number) && (number.indexOf('0x') === 0 || number.indexOf('-0x') === 0)) {\n return new BigNumber(number.replace('0x',''), 16);\n }\n \n return new BigNumber(number.toString(10), 10);\n};\n\n/**\n * Takes and input transforms it into bignumber and if it is negative value, into two's complement\n *\n * @method toTwosComplement\n * @param {Number|String|BigNumber}\n * @return {BigNumber}\n */\nvar toTwosComplement = function (number) {\n var bigNumber = toBigNumber(number);\n if (bigNumber.lessThan(0)) {\n return new BigNumber(\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\", 16).plus(bigNumber).plus(1);\n }\n return bigNumber;\n};\n\n/**\n * Checks if the given string is strictly an address\n *\n * @method isStrictAddress\n * @param {String} address the given HEX adress\n * @return {Boolean}\n*/\nvar isStrictAddress = function (address) {\n return /^0x[0-9a-f]{40}$/.test(address);\n};\n\n/**\n * Checks if the given string is an address\n *\n * @method isAddress\n * @param {String} address the given HEX adress\n * @return {Boolean}\n*/\nvar isAddress = function (address) {\n return /^(0x)?[0-9a-f]{40}$/.test(address);\n};\n\n/**\n * Transforms given string to valid 20 bytes-length addres with 0x prefix\n *\n * @method toAddress\n * @param {String} address\n * @return {String} formatted address\n */\nvar toAddress = function (address) {\n if (isStrictAddress(address)) {\n return address;\n }\n \n if (/^[0-9a-f]{40}$/.test(address)) {\n return '0x' + address;\n }\n\n return '0x' + padLeft(toHex(address).substr(2), 40);\n};\n\n/**\n * Returns true if object is BigNumber, otherwise false\n *\n * @method isBigNumber\n * @param {Object}\n * @return {Boolean} \n */\nvar isBigNumber = function (object) {\n return object instanceof BigNumber ||\n (object && object.constructor && object.constructor.name === 'BigNumber');\n};\n\n/**\n * Returns true if object is string, otherwise false\n * \n * @method isString\n * @param {Object}\n * @return {Boolean}\n */\nvar isString = function (object) {\n return typeof object === 'string' ||\n (object && object.constructor && object.constructor.name === 'String');\n};\n\n/**\n * Returns true if object is function, otherwise false\n *\n * @method isFunction\n * @param {Object}\n * @return {Boolean}\n */\nvar isFunction = function (object) {\n return typeof object === 'function';\n};\n\n/**\n * Returns true if object is Objet, otherwise false\n *\n * @method isObject\n * @param {Object}\n * @return {Boolean}\n */\nvar isObject = function (object) {\n return typeof object === 'object';\n};\n\n/**\n * Returns true if object is boolean, otherwise false\n *\n * @method isBoolean\n * @param {Object}\n * @return {Boolean}\n */\nvar isBoolean = function (object) {\n return typeof object === 'boolean';\n};\n\n/**\n * Returns true if object is array, otherwise false\n *\n * @method isArray\n * @param {Object}\n * @return {Boolean}\n */\nvar isArray = function (object) {\n return object instanceof Array; \n};\n\n/**\n * Returns true if given string is valid json object\n * \n * @method isJson\n * @param {String}\n * @return {Boolean}\n */\nvar isJson = function (str) {\n try {\n return !!JSON.parse(str);\n } catch (e) {\n return false;\n }\n};\n\nmodule.exports = {\n padLeft: padLeft,\n toHex: toHex,\n toDecimal: toDecimal,\n fromDecimal: fromDecimal,\n toAscii: toAscii,\n fromAscii: fromAscii,\n transformToFullName: transformToFullName,\n extractDisplayName: extractDisplayName,\n extractTypeName: extractTypeName,\n toWei: toWei,\n fromWei: fromWei,\n toBigNumber: toBigNumber,\n toTwosComplement: toTwosComplement,\n toAddress: toAddress,\n isBigNumber: isBigNumber,\n isStrictAddress: isStrictAddress,\n isAddress: isAddress,\n isFunction: isFunction,\n isString: isString,\n isObject: isObject,\n isBoolean: isBoolean,\n isArray: isArray,\n isJson: isJson\n};\n\n", - "module.exports={\n \"version\": \"0.3.3\"\n}\n", + "module.exports={\n \"version\": \"0.3.6\"\n}\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file web3.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * Gav Wood \n * @date 2014\n */\n\nvar version = require('./version.json');\nvar net = require('./web3/net');\nvar eth = require('./web3/eth');\nvar db = require('./web3/db');\nvar shh = require('./web3/shh');\nvar watches = require('./web3/watches');\nvar Filter = require('./web3/filter');\nvar utils = require('./utils/utils');\nvar formatters = require('./web3/formatters');\nvar RequestManager = require('./web3/requestmanager');\nvar c = require('./utils/config');\nvar Method = require('./web3/method');\nvar Property = require('./web3/property');\n\nvar web3Methods = [\n new Method({\n name: 'sha3',\n call: 'web3_sha3',\n params: 1\n })\n];\n\nvar web3Properties = [\n new Property({\n name: 'version.client',\n getter: 'web3_clientVersion'\n }),\n new Property({\n name: 'version.network',\n getter: 'net_version',\n inputFormatter: utils.toDecimal\n }),\n new Property({\n name: 'version.ethereum',\n getter: 'eth_protocolVersion',\n inputFormatter: utils.toDecimal\n }),\n new Property({\n name: 'version.whisper',\n getter: 'shh_version',\n inputFormatter: utils.toDecimal\n })\n];\n\n/// creates methods in a given object based on method description on input\n/// setups api calls for these methods\nvar setupMethods = function (obj, methods) {\n methods.forEach(function (method) {\n method.attachToObject(obj);\n });\n};\n\n/// creates properties in a given object based on properties description on input\n/// setups api calls for these properties\nvar setupProperties = function (obj, properties) {\n properties.forEach(function (property) {\n property.attachToObject(obj);\n });\n};\n\n/// setups web3 object, and it's in-browser executed methods\nvar web3 = {};\nweb3.providers = {};\nweb3.version = {};\nweb3.version.api = version.version;\nweb3.eth = {};\n\n/*jshint maxparams:4 */\nweb3.eth.filter = function (fil, eventParams, options, formatter) {\n\n // if its event, treat it differently\n // TODO: simplify and remove\n if (fil._isEvent) {\n return fil(eventParams, options);\n }\n\n // what outputLogFormatter? that's wrong\n //return new Filter(fil, watches.eth(), formatters.outputLogFormatter);\n return new Filter(fil, watches.eth(), formatter || formatters.outputLogFormatter);\n};\n/*jshint maxparams:3 */\n\nweb3.shh = {};\nweb3.shh.filter = function (fil) {\n return new Filter(fil, watches.shh(), formatters.outputPostFormatter);\n};\nweb3.net = {};\nweb3.db = {};\nweb3.setProvider = function (provider) {\n RequestManager.getInstance().setProvider(provider);\n};\nweb3.reset = function () {\n RequestManager.getInstance().reset();\n c.defaultBlock = 'latest';\n c.defaultAccount = undefined;\n};\nweb3.toHex = utils.toHex;\nweb3.toAscii = utils.toAscii;\nweb3.fromAscii = utils.fromAscii;\nweb3.toDecimal = utils.toDecimal;\nweb3.fromDecimal = utils.fromDecimal;\nweb3.toBigNumber = utils.toBigNumber;\nweb3.toWei = utils.toWei;\nweb3.fromWei = utils.fromWei;\nweb3.isAddress = utils.isAddress;\n\n// ADD defaultblock\nObject.defineProperty(web3.eth, 'defaultBlock', {\n get: function () {\n return c.defaultBlock;\n },\n set: function (val) {\n c.defaultBlock = val;\n return val;\n }\n});\n\nObject.defineProperty(web3.eth, 'defaultAccount', {\n get: function () {\n return c.defaultAccount;\n },\n set: function (val) {\n c.defaultAccount = val;\n return val;\n }\n});\n\n/// setups all api methods\nsetupMethods(web3, web3Methods);\nsetupProperties(web3, web3Properties);\nsetupMethods(web3.net, net.methods);\nsetupProperties(web3.net, net.properties);\nsetupMethods(web3.eth, eth.methods);\nsetupProperties(web3.eth, eth.properties);\nsetupMethods(web3.db, db.methods);\nsetupMethods(web3.shh, shh.methods);\n\nmodule.exports = web3;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file contract.js\n * @author Marek Kotewicz \n * @date 2014\n */\n\nvar web3 = require('../web3'); \nvar solAbi = require('../solidity/abi');\nvar utils = require('../utils/utils');\nvar SolidityEvent = require('./event');\nvar SolidityFunction = require('./function');\n\nvar addFunctionsToContract = function (contract, desc) {\n desc.filter(function (json) {\n return json.type === 'function';\n }).map(function (json) {\n return new SolidityFunction(json, contract.address);\n }).forEach(function (f) {\n f.attachToContract(contract);\n });\n};\n\nvar addEventsToContract = function (contract, desc) {\n desc.filter(function (json) {\n return json.type === 'event';\n }).map(function (json) {\n return new SolidityEvent(json, contract.address);\n }).forEach(function (e) {\n e.attachToContract(contract);\n });\n};\n\n/**\n * This method should be called when we want to call / transact some solidity method from javascript\n * it returns an object which has same methods available as solidity contract description\n * usage example: \n *\n * var abi = [{\n * name: 'myMethod',\n * inputs: [{ name: 'a', type: 'string' }],\n * outputs: [{name: 'd', type: 'string' }]\n * }]; // contract abi\n *\n * var MyContract = web3.eth.contract(abi); // creation of contract prototype\n *\n * var contractInstance = new MyContract('0x0123123121');\n *\n * contractInstance.myMethod('this is test string param for call'); // myMethod call (implicit, default)\n * contractInstance.call().myMethod('this is test string param for call'); // myMethod call (explicit)\n * contractInstance.sendTransaction().myMethod('this is test string param for transact'); // myMethod sendTransaction\n *\n * @param abi - abi json description of the contract, which is being created\n * @returns contract object\n */\nvar contract = function (abi) {\n\n // return prototype\n return Contract.bind(null, abi);\n};\n\nvar Contract = function (abi, options) {\n\n this.address = '';\n if (utils.isAddress(options)) {\n this.address = options;\n } else { // is an object!\n // TODO, parse the rest of the args\n options = options || {};\n var args = Array.prototype.slice.call(arguments, 2);\n var bytes = solAbi.formatConstructorParams(abi, args);\n options.data += bytes;\n this.address = web3.eth.sendTransaction(options);\n }\n\n addFunctionsToContract(this, abi);\n addEventsToContract(this, abi);\n};\n\nContract.prototype.call = function () {\n console.error('contract.call is deprecated');\n return this;\n};\n\nContract.prototype.sendTransaction = function () {\n console.error('contract.sendTransact is deprecated');\n return this;\n};\n\nmodule.exports = contract;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file db.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar Method = require('./method');\n\nvar putString = new Method({\n name: 'putString',\n call: 'db_putString',\n params: 3\n});\n\n\nvar getString = new Method({\n name: 'getString',\n call: 'db_getString',\n params: 2\n});\n\nvar putHex = new Method({\n name: 'putHex',\n call: 'db_putHex',\n params: 3\n});\n\nvar getHex = new Method({\n name: 'getHex',\n call: 'db_getHex',\n params: 2\n});\n\nvar methods = [\n putString, getString, putHex, getHex\n];\n\nmodule.exports = {\n methods: methods\n};\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file errors.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nmodule.exports = {\n InvalidNumberOfParams: function () {\n return new Error('Invalid number of input parameters');\n },\n InvalidConnection: function (host){\n return new Error('CONNECTION ERROR: Couldn\\'t connect to node '+ host +', is it running?');\n },\n InvalidProvider: function () {\n return new Error('Providor not set or invalid');\n },\n InvalidResponse: function (result){\n var message = !!result && !!result.error && !!result.error.message ? result.error.message : 'Invalid JSON RPC response';\n return new Error(message);\n }\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/**\n * @file eth.js\n * @author Marek Kotewicz \n * @author Fabian Vogelsteller \n * @date 2015\n */\n\n/**\n * Web3\n * \n * @module web3\n */\n\n/**\n * Eth methods and properties\n *\n * An example method object can look as follows:\n *\n * {\n * name: 'getBlock',\n * call: blockCall,\n * params: 2,\n * outputFormatter: formatters.outputBlockFormatter,\n * inputFormatter: [ // can be a formatter funciton or an array of functions. Where each item in the array will be used for one parameter\n * utils.toHex, // formats paramter 1\n * function(param){ return !!param; } // formats paramter 2\n * ]\n * },\n *\n * @class [web3] eth\n * @constructor\n */\n\n\"use strict\";\n\nvar formatters = require('./formatters');\nvar utils = require('../utils/utils');\nvar Method = require('./method');\nvar Property = require('./property');\n\nvar blockCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? \"eth_getBlockByHash\" : \"eth_getBlockByNumber\";\n};\n\nvar transactionFromBlockCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getTransactionByBlockHashAndIndex' : 'eth_getTransactionByBlockNumberAndIndex';\n};\n\nvar uncleCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getUncleByBlockHashAndIndex' : 'eth_getUncleByBlockNumberAndIndex';\n};\n\nvar getBlockTransactionCountCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getBlockTransactionCountByHash' : 'eth_getBlockTransactionCountByNumber';\n};\n\nvar uncleCountCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getUncleCountByBlockHash' : 'eth_getUncleCountByBlockNumber';\n};\n\n/// @returns an array of objects describing web3.eth api methods\n\nvar getBalance = new Method({\n name: 'getBalance', \n call: 'eth_getBalance', \n params: 2,\n inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter],\n outputFormatter: formatters.outputBigNumberFormatter\n});\n\nvar getStorageAt = new Method({\n name: 'getStorageAt', \n call: 'eth_getStorageAt', \n params: 3,\n inputFormatter: [null, utils.toHex, formatters.inputDefaultBlockNumberFormatter]\n});\n\nvar getCode = new Method({\n name: 'getCode',\n call: 'eth_getCode',\n params: 2,\n inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter]\n});\n\nvar getBlock = new Method({\n name: 'getBlock', \n call: blockCall,\n params: 2,\n inputFormatter: [formatters.inputBlockNumberFormatter, function (val) { return !!val; }],\n outputFormatter: formatters.outputBlockFormatter\n});\n\nvar getUncle = new Method({\n name: 'getUncle',\n call: uncleCall,\n params: 2,\n inputFormatter: [formatters.inputBlockNumberFormatter, utils.toHex],\n outputFormatter: formatters.outputBlockFormatter,\n\n});\n\nvar getCompilers = new Method({\n name: 'getCompilers',\n call: 'eth_getCompilers',\n params: 0\n});\n\nvar getBlockTransactionCount = new Method({\n name: 'getBlockTransactionCount',\n call: getBlockTransactionCountCall,\n params: 1,\n inputFormatter: [formatters.inputBlockNumberFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar getBlockUncleCount = new Method({\n name: 'getBlockUncleCount',\n call: uncleCountCall,\n params: 1,\n inputFormatter: [formatters.inputBlockNumberFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar getTransaction = new Method({\n name: 'getTransaction',\n call: 'eth_getTransactionByHash',\n params: 1,\n outputFormatter: formatters.outputTransactionFormatter\n});\n\nvar getTransactionFromBlock = new Method({\n name: 'getTransactionFromBlock',\n call: transactionFromBlockCall,\n params: 2,\n inputFormatter: [formatters.inputBlockNumberFormatter, utils.toHex],\n outputFormatter: formatters.outputTransactionFormatter\n});\n\nvar getTransactionCount = new Method({\n name: 'getTransactionCount',\n call: 'eth_getTransactionCount',\n params: 2,\n inputFormatter: [null, formatters.inputDefaultBlockNumberFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar sendTransaction = new Method({\n name: 'sendTransaction',\n call: 'eth_sendTransaction',\n params: 1,\n inputFormatter: [formatters.inputTransactionFormatter]\n});\n\nvar call = new Method({\n name: 'call',\n call: 'eth_call',\n params: 2,\n inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter]\n});\n\nvar compileSolidity = new Method({\n name: 'compile.solidity',\n call: 'eth_compileSolidity',\n params: 1\n});\n\nvar compileLLL = new Method({\n name: 'compile.lll',\n call: 'eth_compileLLL',\n params: 1\n});\n\nvar compileSerpent = new Method({\n name: 'compile.serpent',\n call: 'eth_compileSerpent',\n params: 1\n});\n\nvar methods = [\n getBalance,\n getStorageAt,\n getCode,\n getBlock,\n getUncle,\n getCompilers,\n getBlockTransactionCount,\n getBlockUncleCount,\n getTransaction,\n getTransactionFromBlock,\n getTransactionCount,\n call,\n sendTransaction,\n compileSolidity,\n compileLLL,\n compileSerpent,\n];\n\n/// @returns an array of objects describing web3.eth api properties\n\n\n\nvar properties = [\n new Property({\n name: 'coinbase',\n getter: 'eth_coinbase'\n }),\n new Property({\n name: 'mining',\n getter: 'eth_mining'\n }),\n new Property({\n name: 'gasPrice',\n getter: 'eth_gasPrice',\n outputFormatter: formatters.outputBigNumberFormatter\n }),\n new Property({\n name: 'accounts',\n getter: 'eth_accounts'\n }),\n new Property({\n name: 'blockNumber',\n getter: 'eth_blockNumber',\n outputFormatter: utils.toDecimal\n })\n];\n\nmodule.exports = {\n methods: methods,\n properties: properties\n};\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file event.js\n * @author Marek Kotewicz \n * @date 2014\n */\n\nvar utils = require('../utils/utils');\nvar coder = require('../solidity/coder');\nvar web3 = require('../web3');\nvar formatters = require('./formatters');\n\n/**\n * This prototype should be used to create event filters\n */\nvar SolidityEvent = function (json, address) {\n this._params = json.inputs;\n this._name = utils.transformToFullName(json);\n this._address = address;\n this._anonymous = json.anonymous;\n};\n\n/**\n * Should be used to get filtered param types\n *\n * @method types\n * @param {Bool} decide if returned typed should be indexed\n * @return {Array} array of types\n */\nSolidityEvent.prototype.types = function (indexed) {\n return this._params.filter(function (i) {\n return i.indexed === indexed;\n }).map(function (i) {\n return i.type;\n });\n};\n\n/**\n * Should be used to get event display name\n *\n * @method displayName\n * @return {String} event display name\n */\nSolidityEvent.prototype.displayName = function () {\n return utils.extractDisplayName(this._name);\n};\n\n/**\n * Should be used to get event type name\n *\n * @method typeName\n * @return {String} event type name\n */\nSolidityEvent.prototype.typeName = function () {\n return utils.extractTypeName(this._name);\n};\n\n/**\n * Should be used to get event signature\n *\n * @method signature\n * @return {String} event signature\n */\nSolidityEvent.prototype.signature = function () {\n return web3.sha3(web3.fromAscii(this._name)).slice(2);\n};\n\n/**\n * Should be used to encode indexed params and options to one final object\n * \n * @method encode\n * @param {Object} indexed\n * @param {Object} options\n * @return {Object} everything combined together and encoded\n */\nSolidityEvent.prototype.encode = function (indexed, options) {\n indexed = indexed || {};\n options = options || {};\n var result = {};\n\n ['fromBlock', 'toBlock'].filter(function (f) {\n return options[f] !== undefined;\n }).forEach(function (f) {\n result[f] = utils.toHex(options[f]);\n });\n\n result.topics = [];\n\n if (!this._anonymous) {\n result.address = this._address;\n result.topics.push('0x' + this.signature());\n }\n\n var indexedTopics = this._params.filter(function (i) {\n return i.indexed === true;\n }).map(function (i) {\n var value = indexed[i.name];\n if (value === undefined || value === null) {\n return null;\n }\n \n if (utils.isArray(value)) {\n return value.map(function (v) {\n return '0x' + coder.encodeParam(i.type, v);\n });\n }\n return '0x' + coder.encodeParam(i.type, value);\n });\n\n result.topics = result.topics.concat(indexedTopics);\n\n return result;\n};\n\n/**\n * Should be used to decode indexed params and options\n *\n * @method decode\n * @param {Object} data\n * @return {Object} result object with decoded indexed && not indexed params\n */\nSolidityEvent.prototype.decode = function (data) {\n \n data.data = data.data || '';\n data.topics = data.topics || [];\n\n var argTopics = this._anonymous ? data.topics : data.topics.slice(1);\n var indexedData = argTopics.map(function (topics) { return topics.slice(2); }).join(\"\");\n var indexedParams = coder.decodeParams(this.types(true), indexedData); \n\n var notIndexedData = data.data.slice(2);\n var notIndexedParams = coder.decodeParams(this.types(false), notIndexedData);\n \n var result = formatters.outputLogFormatter(data);\n result.event = this.displayName();\n result.address = data.address;\n\n result.args = this._params.reduce(function (acc, current) {\n acc[current.name] = current.indexed ? indexedParams.shift() : notIndexedParams.shift();\n return acc;\n }, {});\n\n delete result.data;\n delete result.topics;\n\n return result;\n};\n\n/**\n * Should be used to create new filter object from event\n *\n * @method execute\n * @param {Object} indexed\n * @param {Object} options\n * @return {Object} filter object\n */\nSolidityEvent.prototype.execute = function (indexed, options) {\n var o = this.encode(indexed, options);\n var formatter = this.decode.bind(this);\n return web3.eth.filter(o, undefined, undefined, formatter);\n};\n\n/**\n * Should be used to attach event to contract object\n *\n * @method attachToContract\n * @param {Contract}\n */\nSolidityEvent.prototype.attachToContract = function (contract) {\n var execute = this.execute.bind(this);\n var displayName = this.displayName();\n if (!contract[displayName]) {\n contract[displayName] = execute;\n }\n contract[displayName][this.typeName()] = this.execute.bind(this, contract);\n};\n\nmodule.exports = SolidityEvent;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/**\n * @file eth.js\n * @author Marek Kotewicz \n * @author Fabian Vogelsteller \n * @date 2015\n */\n\n/**\n * Web3\n *\n * @module web3\n */\n\n/**\n * Eth methods and properties\n *\n * An example method object can look as follows:\n *\n * {\n * name: 'getBlock',\n * call: blockCall,\n * params: 2,\n * outputFormatter: formatters.outputBlockFormatter,\n * inputFormatter: [ // can be a formatter funciton or an array of functions. Where each item in the array will be used for one parameter\n * utils.toHex, // formats paramter 1\n * function(param){ return !!param; } // formats paramter 2\n * ]\n * },\n *\n * @class [web3] eth\n * @constructor\n */\n\n\"use strict\";\n\nvar formatters = require('./formatters');\nvar utils = require('../utils/utils');\nvar Method = require('./method');\nvar Property = require('./property');\n\nvar blockCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? \"eth_getBlockByHash\" : \"eth_getBlockByNumber\";\n};\n\nvar transactionFromBlockCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getTransactionByBlockHashAndIndex' : 'eth_getTransactionByBlockNumberAndIndex';\n};\n\nvar uncleCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getUncleByBlockHashAndIndex' : 'eth_getUncleByBlockNumberAndIndex';\n};\n\nvar getBlockTransactionCountCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getBlockTransactionCountByHash' : 'eth_getBlockTransactionCountByNumber';\n};\n\nvar uncleCountCall = function (args) {\n return (utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getUncleCountByBlockHash' : 'eth_getUncleCountByBlockNumber';\n};\n\n/// @returns an array of objects describing web3.eth api methods\n\nvar getBalance = new Method({\n name: 'getBalance',\n call: 'eth_getBalance',\n params: 2,\n inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter],\n outputFormatter: formatters.outputBigNumberFormatter\n});\n\nvar getStorageAt = new Method({\n name: 'getStorageAt',\n call: 'eth_getStorageAt',\n params: 3,\n inputFormatter: [null, utils.toHex, formatters.inputDefaultBlockNumberFormatter]\n});\n\nvar getCode = new Method({\n name: 'getCode',\n call: 'eth_getCode',\n params: 2,\n inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter]\n});\n\nvar getBlock = new Method({\n name: 'getBlock',\n call: blockCall,\n params: 2,\n inputFormatter: [formatters.inputBlockNumberFormatter, function (val) { return !!val; }],\n outputFormatter: formatters.outputBlockFormatter\n});\n\nvar getUncle = new Method({\n name: 'getUncle',\n call: uncleCall,\n params: 2,\n inputFormatter: [formatters.inputBlockNumberFormatter, utils.toHex],\n outputFormatter: formatters.outputBlockFormatter,\n\n});\n\nvar getCompilers = new Method({\n name: 'getCompilers',\n call: 'eth_getCompilers',\n params: 0\n});\n\nvar getBlockTransactionCount = new Method({\n name: 'getBlockTransactionCount',\n call: getBlockTransactionCountCall,\n params: 1,\n inputFormatter: [formatters.inputBlockNumberFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar getBlockUncleCount = new Method({\n name: 'getBlockUncleCount',\n call: uncleCountCall,\n params: 1,\n inputFormatter: [formatters.inputBlockNumberFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar getTransaction = new Method({\n name: 'getTransaction',\n call: 'eth_getTransactionByHash',\n params: 1,\n outputFormatter: formatters.outputTransactionFormatter\n});\n\nvar getTransactionFromBlock = new Method({\n name: 'getTransactionFromBlock',\n call: transactionFromBlockCall,\n params: 2,\n inputFormatter: [formatters.inputBlockNumberFormatter, utils.toHex],\n outputFormatter: formatters.outputTransactionFormatter\n});\n\nvar getTransactionCount = new Method({\n name: 'getTransactionCount',\n call: 'eth_getTransactionCount',\n params: 2,\n inputFormatter: [null, formatters.inputDefaultBlockNumberFormatter],\n outputFormatter: utils.toDecimal\n});\n\nvar sendTransaction = new Method({\n name: 'sendTransaction',\n call: 'eth_sendTransaction',\n params: 1,\n inputFormatter: [formatters.inputTransactionFormatter]\n});\n\nvar call = new Method({\n name: 'call',\n call: 'eth_call',\n params: 2,\n inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter]\n});\n\nvar compileSolidity = new Method({\n name: 'compile.solidity',\n call: 'eth_compileSolidity',\n params: 1\n});\n\nvar compileLLL = new Method({\n name: 'compile.lll',\n call: 'eth_compileLLL',\n params: 1\n});\n\nvar compileSerpent = new Method({\n name: 'compile.serpent',\n call: 'eth_compileSerpent',\n params: 1\n});\n\nvar methods = [\n getBalance,\n getStorageAt,\n getCode,\n getBlock,\n getUncle,\n getCompilers,\n getBlockTransactionCount,\n getBlockUncleCount,\n getTransaction,\n getTransactionFromBlock,\n getTransactionCount,\n call,\n sendTransaction,\n compileSolidity,\n compileLLL,\n compileSerpent,\n];\n\n/// @returns an array of objects describing web3.eth api properties\n\n\n\nvar properties = [\n new Property({\n name: 'coinbase',\n getter: 'eth_coinbase'\n }),\n new Property({\n name: 'mining',\n getter: 'eth_mining'\n }),\n new Property({\n name: 'hashrate',\n getter: 'eth_hashrate',\n outputFormatter: utils.toDecimal\n }),\n new Property({\n name: 'gasPrice',\n getter: 'eth_gasPrice',\n outputFormatter: formatters.outputBigNumberFormatter\n }),\n new Property({\n name: 'accounts',\n getter: 'eth_accounts'\n }),\n new Property({\n name: 'blockNumber',\n getter: 'eth_blockNumber',\n outputFormatter: utils.toDecimal\n })\n];\n\nmodule.exports = {\n methods: methods,\n properties: properties\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file event.js\n * @author Marek Kotewicz \n * @date 2014\n */\n\nvar utils = require('../utils/utils');\nvar coder = require('../solidity/coder');\nvar web3 = require('../web3');\nvar formatters = require('./formatters');\n\n/**\n * This prototype should be used to create event filters\n */\nvar SolidityEvent = function (json, address) {\n this._params = json.inputs;\n this._name = utils.transformToFullName(json);\n this._address = address;\n this._anonymous = json.anonymous;\n};\n\n/**\n * Should be used to get filtered param types\n *\n * @method types\n * @param {Bool} decide if returned typed should be indexed\n * @return {Array} array of types\n */\nSolidityEvent.prototype.types = function (indexed) {\n return this._params.filter(function (i) {\n return i.indexed === indexed;\n }).map(function (i) {\n return i.type;\n });\n};\n\n/**\n * Should be used to get event display name\n *\n * @method displayName\n * @return {String} event display name\n */\nSolidityEvent.prototype.displayName = function () {\n return utils.extractDisplayName(this._name);\n};\n\n/**\n * Should be used to get event type name\n *\n * @method typeName\n * @return {String} event type name\n */\nSolidityEvent.prototype.typeName = function () {\n return utils.extractTypeName(this._name);\n};\n\n/**\n * Should be used to get event signature\n *\n * @method signature\n * @return {String} event signature\n */\nSolidityEvent.prototype.signature = function () {\n return web3.sha3(web3.fromAscii(this._name)).slice(2);\n};\n\n/**\n * Should be used to encode indexed params and options to one final object\n * \n * @method encode\n * @param {Object} indexed\n * @param {Object} options\n * @return {Object} everything combined together and encoded\n */\nSolidityEvent.prototype.encode = function (indexed, options) {\n indexed = indexed || {};\n options = options || {};\n var result = {};\n\n ['fromBlock', 'toBlock'].filter(function (f) {\n return options[f] !== undefined;\n }).forEach(function (f) {\n result[f] = formatters.inputBlockNumberFormatter(options[f]);\n });\n\n result.topics = [];\n\n if (!this._anonymous) {\n result.address = this._address;\n result.topics.push('0x' + this.signature());\n }\n\n var indexedTopics = this._params.filter(function (i) {\n return i.indexed === true;\n }).map(function (i) {\n var value = indexed[i.name];\n if (value === undefined || value === null) {\n return null;\n }\n \n if (utils.isArray(value)) {\n return value.map(function (v) {\n return '0x' + coder.encodeParam(i.type, v);\n });\n }\n return '0x' + coder.encodeParam(i.type, value);\n });\n\n result.topics = result.topics.concat(indexedTopics);\n\n return result;\n};\n\n/**\n * Should be used to decode indexed params and options\n *\n * @method decode\n * @param {Object} data\n * @return {Object} result object with decoded indexed && not indexed params\n */\nSolidityEvent.prototype.decode = function (data) {\n \n data.data = data.data || '';\n data.topics = data.topics || [];\n\n var argTopics = this._anonymous ? data.topics : data.topics.slice(1);\n var indexedData = argTopics.map(function (topics) { return topics.slice(2); }).join(\"\");\n var indexedParams = coder.decodeParams(this.types(true), indexedData); \n\n var notIndexedData = data.data.slice(2);\n var notIndexedParams = coder.decodeParams(this.types(false), notIndexedData);\n \n var result = formatters.outputLogFormatter(data);\n result.event = this.displayName();\n result.address = data.address;\n\n result.args = this._params.reduce(function (acc, current) {\n acc[current.name] = current.indexed ? indexedParams.shift() : notIndexedParams.shift();\n return acc;\n }, {});\n\n delete result.data;\n delete result.topics;\n\n return result;\n};\n\n/**\n * Should be used to create new filter object from event\n *\n * @method execute\n * @param {Object} indexed\n * @param {Object} options\n * @return {Object} filter object\n */\nSolidityEvent.prototype.execute = function (indexed, options) {\n var o = this.encode(indexed, options);\n var formatter = this.decode.bind(this);\n return web3.eth.filter(o, undefined, undefined, formatter);\n};\n\n/**\n * Should be used to attach event to contract object\n *\n * @method attachToContract\n * @param {Contract}\n */\nSolidityEvent.prototype.attachToContract = function (contract) {\n var execute = this.execute.bind(this);\n var displayName = this.displayName();\n if (!contract[displayName]) {\n contract[displayName] = execute;\n }\n contract[displayName][this.typeName()] = this.execute.bind(this, contract);\n};\n\nmodule.exports = SolidityEvent;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file filter.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * Gav Wood \n * @date 2014\n */\n\nvar RequestManager = require('./requestmanager');\nvar formatters = require('./formatters');\nvar utils = require('../utils/utils');\n\n/**\n* Converts a given topic to a hex string, but also allows null values.\n*\n* @param {Mixed} value\n* @return {String}\n*/\nvar toTopic = function(value){\n\n if(value === null || typeof value === 'undefined')\n return null;\n\n value = String(value);\n\n if(value.indexOf('0x') === 0)\n return value;\n else\n return utils.fromAscii(value);\n};\n\n/// This method should be called on options object, to verify deprecated properties && lazy load dynamic ones\n/// @param should be string or object\n/// @returns options string or object\nvar getOptions = function (options) {\n\n if (utils.isString(options)) {\n return options;\n } \n\n options = options || {};\n\n // make sure topics, get converted to hex\n options.topics = options.topics || [];\n options.topics = options.topics.map(function(topic){\n return (utils.isArray(topic)) ? topic.map(toTopic) : toTopic(topic);\n });\n\n // lazy load\n return {\n topics: options.topics,\n to: options.to,\n address: options.address,\n fromBlock: formatters.inputBlockNumberFormatter(options.fromBlock),\n toBlock: formatters.inputBlockNumberFormatter(options.toBlock) \n }; \n};\n\nvar Filter = function (options, methods, formatter) {\n var implementation = {};\n methods.forEach(function (method) {\n method.attachToObject(implementation);\n });\n this.options = getOptions(options);\n this.implementation = implementation;\n this.callbacks = [];\n this.formatter = formatter;\n this.filterId = this.implementation.newFilter(this.options);\n};\n\nFilter.prototype.watch = function (callback) {\n this.callbacks.push(callback);\n var self = this;\n\n var onMessage = function (error, messages) {\n if (error) {\n return self.callbacks.forEach(function (callback) {\n callback(error);\n });\n }\n\n messages.forEach(function (message) {\n message = self.formatter ? self.formatter(message) : message;\n self.callbacks.forEach(function (callback) {\n callback(null, message);\n });\n });\n };\n\n // call getFilterLogs on start\n if (!utils.isString(this.options)) {\n this.get(function (err, messages) {\n // don't send all the responses to all the watches again... just to this one\n if (err) {\n callback(err);\n }\n\n messages.forEach(function (message) {\n callback(null, message);\n });\n });\n }\n\n RequestManager.getInstance().startPolling({\n method: this.implementation.poll.call,\n params: [this.filterId],\n }, this.filterId, onMessage, this.stopWatching.bind(this));\n};\n\nFilter.prototype.stopWatching = function () {\n RequestManager.getInstance().stopPolling(this.filterId);\n this.implementation.uninstallFilter(this.filterId);\n this.callbacks = [];\n};\n\nFilter.prototype.get = function (callback) {\n var self = this;\n if (utils.isFunction(callback)) {\n this.implementation.getLogs(this.filterId, function(err, res){\n if (err) {\n callback(err);\n } else {\n callback(null, res.map(function (log) {\n return self.formatter ? self.formatter(log) : log;\n }));\n }\n });\n } else {\n var logs = this.implementation.getLogs(this.filterId);\n return logs.map(function (log) {\n return self.formatter ? self.formatter(log) : log;\n });\n }\n};\n\nmodule.exports = Filter;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file formatters.js\n * @author Marek Kotewicz \n * @author Fabian Vogelsteller \n * @date 2015\n */\n\nvar utils = require('../utils/utils');\nvar config = require('../utils/config');\n\n/**\n * Should the format output to a big number\n *\n * @method outputBigNumberFormatter\n * @param {String|Number|BigNumber}\n * @returns {BigNumber} object\n */\nvar outputBigNumberFormatter = function (number) {\n return utils.toBigNumber(number);\n};\n\nvar isPredefinedBlockNumber = function (blockNumber) {\n return blockNumber === 'latest' || blockNumber === 'pending' || blockNumber === 'earliest';\n};\n\nvar inputDefaultBlockNumberFormatter = function (blockNumber) {\n if (blockNumber === undefined) {\n return config.defaultBlock;\n }\n return inputBlockNumberFormatter(blockNumber);\n};\n\nvar inputBlockNumberFormatter = function (blockNumber) {\n if (blockNumber === undefined) {\n return undefined;\n } else if (isPredefinedBlockNumber(blockNumber)) {\n return blockNumber;\n }\n return utils.toHex(blockNumber);\n};\n\n/**\n * Formats the input of a transaction and converts all values to HEX\n *\n * @method inputTransactionFormatter\n * @param {Object} transaction options\n * @returns object\n*/\nvar inputTransactionFormatter = function (options){\n\n options.from = options.from || config.defaultAccount;\n\n // make code -> data\n if (options.code) {\n options.data = options.code;\n delete options.code;\n }\n\n ['gasPrice', 'gas', 'value'].filter(function (key) {\n return options[key] !== undefined;\n }).forEach(function(key){\n options[key] = utils.fromDecimal(options[key]);\n });\n\n return options; \n};\n\n/**\n * Formats the output of a transaction to its proper values\n * \n * @method outputTransactionFormatter\n * @param {Object} transaction\n * @returns {Object} transaction\n*/\nvar outputTransactionFormatter = function (tx){\n tx.blockNumber = utils.toDecimal(tx.blockNumber);\n tx.transactionIndex = utils.toDecimal(tx.transactionIndex);\n tx.nonce = utils.toDecimal(tx.nonce);\n tx.gas = utils.toDecimal(tx.gas);\n tx.gasPrice = utils.toBigNumber(tx.gasPrice);\n tx.value = utils.toBigNumber(tx.value);\n return tx;\n};\n\n/**\n * Formats the output of a block to its proper values\n *\n * @method outputBlockFormatter\n * @param {Object} block object \n * @returns {Object} block object\n*/\nvar outputBlockFormatter = function(block) {\n\n // transform to number\n block.gasLimit = utils.toDecimal(block.gasLimit);\n block.gasUsed = utils.toDecimal(block.gasUsed);\n block.size = utils.toDecimal(block.size);\n block.timestamp = utils.toDecimal(block.timestamp);\n block.number = utils.toDecimal(block.number);\n\n block.difficulty = utils.toBigNumber(block.difficulty);\n block.totalDifficulty = utils.toBigNumber(block.totalDifficulty);\n\n if (utils.isArray(block.transactions)) {\n block.transactions.forEach(function(item){\n if(!utils.isString(item))\n return outputTransactionFormatter(item);\n });\n }\n\n return block;\n};\n\n/**\n * Formats the output of a log\n * \n * @method outputLogFormatter\n * @param {Object} log object\n * @returns {Object} log\n*/\nvar outputLogFormatter = function(log) {\n if (log === null) { // 'pending' && 'latest' filters are nulls\n return null;\n }\n\n log.blockNumber = utils.toDecimal(log.blockNumber);\n log.transactionIndex = utils.toDecimal(log.transactionIndex);\n log.logIndex = utils.toDecimal(log.logIndex);\n\n return log;\n};\n\n/**\n * Formats the input of a whisper post and converts all values to HEX\n *\n * @method inputPostFormatter\n * @param {Object} transaction object\n * @returns {Object}\n*/\nvar inputPostFormatter = function(post) {\n\n post.payload = utils.toHex(post.payload);\n post.ttl = utils.fromDecimal(post.ttl);\n post.workToProve = utils.fromDecimal(post.workToProve);\n post.priority = utils.fromDecimal(post.priority);\n\n // fallback\n if (!utils.isArray(post.topics)) {\n post.topics = post.topics ? [post.topics] : [];\n }\n\n // format the following options\n post.topics = post.topics.map(function(topic){\n return utils.fromAscii(topic);\n });\n\n return post; \n};\n\n/**\n * Formats the output of a received post message\n *\n * @method outputPostFormatter\n * @param {Object}\n * @returns {Object}\n */\nvar outputPostFormatter = function(post){\n\n post.expiry = utils.toDecimal(post.expiry);\n post.sent = utils.toDecimal(post.sent);\n post.ttl = utils.toDecimal(post.ttl);\n post.workProved = utils.toDecimal(post.workProved);\n post.payloadRaw = post.payload;\n post.payload = utils.toAscii(post.payload);\n\n if (utils.isJson(post.payload)) {\n post.payload = JSON.parse(post.payload);\n }\n\n // format the following options\n if (!post.topics) {\n post.topics = [];\n }\n post.topics = post.topics.map(function(topic){\n return utils.toAscii(topic);\n });\n\n return post;\n};\n\nmodule.exports = {\n inputDefaultBlockNumberFormatter: inputDefaultBlockNumberFormatter,\n inputBlockNumberFormatter: inputBlockNumberFormatter,\n inputTransactionFormatter: inputTransactionFormatter,\n inputPostFormatter: inputPostFormatter,\n outputBigNumberFormatter: outputBigNumberFormatter,\n outputTransactionFormatter: outputTransactionFormatter,\n outputBlockFormatter: outputBlockFormatter,\n outputLogFormatter: outputLogFormatter,\n outputPostFormatter: outputPostFormatter\n};\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file formatters.js\n * @author Marek Kotewicz \n * @author Fabian Vogelsteller \n * @date 2015\n */\n\nvar utils = require('../utils/utils');\nvar config = require('../utils/config');\n\n/**\n * Should the format output to a big number\n *\n * @method outputBigNumberFormatter\n * @param {String|Number|BigNumber}\n * @returns {BigNumber} object\n */\nvar outputBigNumberFormatter = function (number) {\n return utils.toBigNumber(number);\n};\n\nvar isPredefinedBlockNumber = function (blockNumber) {\n return blockNumber === 'latest' || blockNumber === 'pending' || blockNumber === 'earliest';\n};\n\nvar inputDefaultBlockNumberFormatter = function (blockNumber) {\n if (blockNumber === undefined) {\n return config.defaultBlock;\n }\n return inputBlockNumberFormatter(blockNumber);\n};\n\nvar inputBlockNumberFormatter = function (blockNumber) {\n if (blockNumber === undefined) {\n return undefined;\n } else if (isPredefinedBlockNumber(blockNumber)) {\n return blockNumber;\n }\n return utils.toHex(blockNumber);\n};\n\n/**\n * Formats the input of a transaction and converts all values to HEX\n *\n * @method inputTransactionFormatter\n * @param {Object} transaction options\n * @returns object\n*/\nvar inputTransactionFormatter = function (options){\n\n options.from = options.from || config.defaultAccount;\n\n // make code -> data\n if (options.code) {\n options.data = options.code;\n delete options.code;\n }\n\n ['gasPrice', 'gas', 'value', 'nonce'].filter(function (key) {\n return options[key] !== undefined;\n }).forEach(function(key){\n options[key] = utils.fromDecimal(options[key]);\n });\n\n return options; \n};\n\n/**\n * Formats the output of a transaction to its proper values\n * \n * @method outputTransactionFormatter\n * @param {Object} transaction\n * @returns {Object} transaction\n*/\nvar outputTransactionFormatter = function (tx){\n tx.blockNumber = utils.toDecimal(tx.blockNumber);\n tx.transactionIndex = utils.toDecimal(tx.transactionIndex);\n tx.nonce = utils.toDecimal(tx.nonce);\n tx.gas = utils.toDecimal(tx.gas);\n tx.gasPrice = utils.toBigNumber(tx.gasPrice);\n tx.value = utils.toBigNumber(tx.value);\n return tx;\n};\n\n/**\n * Formats the output of a block to its proper values\n *\n * @method outputBlockFormatter\n * @param {Object} block object \n * @returns {Object} block object\n*/\nvar outputBlockFormatter = function(block) {\n\n // transform to number\n block.gasLimit = utils.toDecimal(block.gasLimit);\n block.gasUsed = utils.toDecimal(block.gasUsed);\n block.size = utils.toDecimal(block.size);\n block.timestamp = utils.toDecimal(block.timestamp);\n block.number = utils.toDecimal(block.number);\n\n block.difficulty = utils.toBigNumber(block.difficulty);\n block.totalDifficulty = utils.toBigNumber(block.totalDifficulty);\n\n if (utils.isArray(block.transactions)) {\n block.transactions.forEach(function(item){\n if(!utils.isString(item))\n return outputTransactionFormatter(item);\n });\n }\n\n return block;\n};\n\n/**\n * Formats the output of a log\n * \n * @method outputLogFormatter\n * @param {Object} log object\n * @returns {Object} log\n*/\nvar outputLogFormatter = function(log) {\n if (log === null) { // 'pending' && 'latest' filters are nulls\n return null;\n }\n\n log.blockNumber = utils.toDecimal(log.blockNumber);\n log.transactionIndex = utils.toDecimal(log.transactionIndex);\n log.logIndex = utils.toDecimal(log.logIndex);\n\n return log;\n};\n\n/**\n * Formats the input of a whisper post and converts all values to HEX\n *\n * @method inputPostFormatter\n * @param {Object} transaction object\n * @returns {Object}\n*/\nvar inputPostFormatter = function(post) {\n\n post.payload = utils.toHex(post.payload);\n post.ttl = utils.fromDecimal(post.ttl);\n post.workToProve = utils.fromDecimal(post.workToProve);\n post.priority = utils.fromDecimal(post.priority);\n\n // fallback\n if (!utils.isArray(post.topics)) {\n post.topics = post.topics ? [post.topics] : [];\n }\n\n // format the following options\n post.topics = post.topics.map(function(topic){\n return utils.fromAscii(topic);\n });\n\n return post; \n};\n\n/**\n * Formats the output of a received post message\n *\n * @method outputPostFormatter\n * @param {Object}\n * @returns {Object}\n */\nvar outputPostFormatter = function(post){\n\n post.expiry = utils.toDecimal(post.expiry);\n post.sent = utils.toDecimal(post.sent);\n post.ttl = utils.toDecimal(post.ttl);\n post.workProved = utils.toDecimal(post.workProved);\n post.payloadRaw = post.payload;\n post.payload = utils.toAscii(post.payload);\n\n if (utils.isJson(post.payload)) {\n post.payload = JSON.parse(post.payload);\n }\n\n // format the following options\n if (!post.topics) {\n post.topics = [];\n }\n post.topics = post.topics.map(function(topic){\n return utils.toAscii(topic);\n });\n\n return post;\n};\n\nmodule.exports = {\n inputDefaultBlockNumberFormatter: inputDefaultBlockNumberFormatter,\n inputBlockNumberFormatter: inputBlockNumberFormatter,\n inputTransactionFormatter: inputTransactionFormatter,\n inputPostFormatter: inputPostFormatter,\n outputBigNumberFormatter: outputBigNumberFormatter,\n outputTransactionFormatter: outputTransactionFormatter,\n outputBlockFormatter: outputBlockFormatter,\n outputLogFormatter: outputLogFormatter,\n outputPostFormatter: outputPostFormatter\n};\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** \n * @file function.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar web3 = require('../web3');\nvar coder = require('../solidity/coder');\nvar utils = require('../utils/utils');\n\n/**\n * This prototype should be used to call/sendTransaction to solidity functions\n */\nvar SolidityFunction = function (json, address) {\n this._inputTypes = json.inputs.map(function (i) {\n return i.type;\n });\n this._outputTypes = json.outputs.map(function (i) {\n return i.type;\n });\n this._constant = json.constant;\n this._name = utils.transformToFullName(json);\n this._address = address;\n};\n\n/**\n * Should be used to create payload from arguments\n *\n * @method toPayload\n * @param {...} solidity function params\n * @param {Object} optional payload options\n */\nSolidityFunction.prototype.toPayload = function () {\n var args = Array.prototype.slice.call(arguments);\n var options = {};\n if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) {\n options = args.pop();\n }\n options.to = this._address;\n options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args);\n return options;\n};\n\n/**\n * Should be used to get function signature\n *\n * @method signature\n * @return {String} function signature\n */\nSolidityFunction.prototype.signature = function () {\n return web3.sha3(web3.fromAscii(this._name)).slice(2, 10);\n};\n\n/**\n * Should be used to call function\n * \n * @method call\n * @param {Object} options\n * @return {String} output bytes\n */\nSolidityFunction.prototype.call = function () {\n var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments));\n var output = web3.eth.call(payload);\n output = output.length >= 2 ? output.slice(2) : output;\n var result = coder.decodeParams(this._outputTypes, output);\n return result.length === 1 ? result[0] : result;\n};\n\n/**\n * Should be used to sendTransaction to solidity function\n *\n * @method sendTransaction\n * @param {Object} options\n */\nSolidityFunction.prototype.sendTransaction = function () {\n var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments));\n web3.eth.sendTransaction(payload);\n};\n\n/**\n * Should be used to get function display name\n *\n * @method displayName\n * @return {String} display name of the function\n */\nSolidityFunction.prototype.displayName = function () {\n return utils.extractDisplayName(this._name);\n};\n\n/**\n * Should be used to get function type name\n * \n * @method typeName\n * @return {String} type name of the function\n */\nSolidityFunction.prototype.typeName = function () {\n return utils.extractTypeName(this._name);\n};\n\n/**\n * Should be called to execute function\n *\n * @method execute\n */\nSolidityFunction.prototype.execute = function () {\n var transaction = !this._constant;\n \n // send transaction\n if (transaction) {\n return this.sendTransaction.apply(this, Array.prototype.slice.call(arguments));\n }\n\n // call\n return this.call.apply(this, Array.prototype.slice.call(arguments));\n};\n\n/**\n * Should be called to attach function to contract\n *\n * @method attachToContract\n * @param {Contract}\n */\nSolidityFunction.prototype.attachToContract = function (contract) {\n var execute = this.execute.bind(this);\n execute.call = this.call.bind(this);\n execute.sendTransaction = this.sendTransaction.bind(this);\n var displayName = this.displayName();\n if (!contract[displayName]) {\n contract[displayName] = execute;\n }\n contract[displayName][this.typeName()] = execute; // circular!!!!\n};\n\nmodule.exports = SolidityFunction;\n\n", - "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file httpprovider.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * @date 2014\n */\n\n\"use strict\";\n\nvar XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\nvar errors = require('./errors');\n\nvar HttpProvider = function (host) {\n this.host = host || 'http://localhost:8545';\n};\n\nHttpProvider.prototype.send = function (payload) {\n var request = new XMLHttpRequest();\n\n request.open('POST', this.host, false);\n \n try {\n request.send(JSON.stringify(payload));\n } catch(error) {\n throw errors.InvalidConnection(this.host);\n }\n\n\n // check request.status\n // TODO: throw an error here! it cannot silently fail!!!\n //if (request.status !== 200) {\n //return;\n //}\n return JSON.parse(request.responseText);\n};\n\nHttpProvider.prototype.sendAsync = function (payload, callback) {\n var request = new XMLHttpRequest();\n request.onreadystatechange = function() {\n if (request.readyState === 4) {\n // TODO: handle the error properly here!!!\n callback(null, JSON.parse(request.responseText));\n }\n };\n\n request.open('POST', this.host, true);\n\n try {\n request.send(JSON.stringify(payload));\n } catch(error) {\n callback(errors.InvalidConnection(this.host));\n }\n};\n\nmodule.exports = HttpProvider;\n\n", + "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file httpprovider.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * Fabian Vogelsteller \n * @date 2014\n */\n\n\"use strict\";\n\nvar XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\nvar errors = require('./errors');\n\nvar HttpProvider = function (host) {\n this.host = host || 'http://localhost:8545';\n};\n\nHttpProvider.prototype.send = function (payload) {\n var request = new XMLHttpRequest();\n\n request.open('POST', this.host, false);\n \n try {\n request.send(JSON.stringify(payload));\n } catch(error) {\n throw errors.InvalidConnection(this.host);\n }\n\n\n // check request.status\n // TODO: throw an error here! it cannot silently fail!!!\n //if (request.status !== 200) {\n //return;\n //}\n\n var result = request.responseText;\n\n try {\n result = JSON.parse(result);\n } catch(e) {\n throw errors.InvalidResponse(result); \n }\n\n return result;\n};\n\nHttpProvider.prototype.sendAsync = function (payload, callback) {\n var request = new XMLHttpRequest();\n request.onreadystatechange = function() {\n if (request.readyState === 4) {\n var result = request.responseText;\n var error = null;\n\n try {\n result = JSON.parse(result);\n } catch(e) {\n error = errors.InvalidResponse(result); \n }\n\n callback(error, result);\n }\n };\n\n request.open('POST', this.host, true);\n\n try {\n request.send(JSON.stringify(payload));\n } catch(error) {\n callback(errors.InvalidConnection(this.host));\n }\n};\n\nmodule.exports = HttpProvider;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file jsonrpc.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar Jsonrpc = function () {\n // singleton pattern\n if (arguments.callee._singletonInstance) {\n return arguments.callee._singletonInstance;\n }\n arguments.callee._singletonInstance = this;\n\n this.messageId = 1;\n};\n\n/**\n * @return {Jsonrpc} singleton\n */\nJsonrpc.getInstance = function () {\n var instance = new Jsonrpc();\n return instance;\n};\n\n/**\n * Should be called to valid json create payload object\n *\n * @method toPayload\n * @param {Function} method of jsonrpc call, required\n * @param {Array} params, an array of method params, optional\n * @returns {Object} valid jsonrpc payload object\n */\nJsonrpc.prototype.toPayload = function (method, params) {\n if (!method)\n console.error('jsonrpc method should be specified!');\n\n return {\n jsonrpc: '2.0',\n method: method,\n params: params || [],\n id: this.messageId++\n };\n};\n\n/**\n * Should be called to check if jsonrpc response is valid\n *\n * @method isValidResponse\n * @param {Object}\n * @returns {Boolean} true if response is valid, otherwise false\n */\nJsonrpc.prototype.isValidResponse = function (response) {\n return !!response &&\n !response.error &&\n response.jsonrpc === '2.0' &&\n typeof response.id === 'number' &&\n response.result !== undefined; // only undefined is not valid json object\n};\n\n/**\n * Should be called to create batch payload object\n *\n * @method toBatchPayload\n * @param {Array} messages, an array of objects with method (required) and params (optional) fields\n * @returns {Array} batch payload\n */\nJsonrpc.prototype.toBatchPayload = function (messages) {\n var self = this;\n return messages.map(function (message) {\n return self.toPayload(message.method, message.params);\n });\n};\n\nmodule.exports = Jsonrpc;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/**\n * @file method.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar RequestManager = require('./requestmanager');\nvar utils = require('../utils/utils');\nvar errors = require('./errors');\n\nvar Method = function (options) {\n this.name = options.name;\n this.call = options.call;\n this.params = options.params || 0;\n this.inputFormatter = options.inputFormatter;\n this.outputFormatter = options.outputFormatter;\n};\n\n/**\n * Should be used to determine name of the jsonrpc method based on arguments\n *\n * @method getCall\n * @param {Array} arguments\n * @return {String} name of jsonrpc method\n */\nMethod.prototype.getCall = function (args) {\n return utils.isFunction(this.call) ? this.call(args) : this.call;\n};\n\n/**\n * Should be used to extract callback from array of arguments. Modifies input param\n *\n * @method extractCallback\n * @param {Array} arguments\n * @return {Function|Null} callback, if exists\n */\nMethod.prototype.extractCallback = function (args) {\n if (utils.isFunction(args[args.length - 1])) {\n return args.pop(); // modify the args array!\n }\n return null;\n};\n\n/**\n * Should be called to check if the number of arguments is correct\n * \n * @method validateArgs\n * @param {Array} arguments\n * @throws {Error} if it is not\n */\nMethod.prototype.validateArgs = function (args) {\n if (args.length !== this.params) {\n throw errors.InvalidNumberOfParams();\n }\n};\n\n/**\n * Should be called to format input args of method\n * \n * @method formatInput\n * @param {Array}\n * @return {Array}\n */\nMethod.prototype.formatInput = function (args) {\n if (!this.inputFormatter) {\n return args;\n }\n\n return this.inputFormatter.map(function (formatter, index) {\n return formatter ? formatter(args[index]) : args[index];\n });\n};\n\n/**\n * Should be called to format output(result) of method\n *\n * @method formatOutput\n * @param {Object}\n * @return {Object}\n */\nMethod.prototype.formatOutput = function (result) {\n return this.outputFormatter && result !== null ? this.outputFormatter(result) : result;\n};\n\n/**\n * Should attach function to method\n * \n * @method attachToObject\n * @param {Object}\n * @param {Function}\n */\nMethod.prototype.attachToObject = function (obj) {\n var func = this.send.bind(this);\n func.call = this.call; // that's ugly. filter.js uses it\n var name = this.name.split('.');\n if (name.length > 1) {\n obj[name[0]] = obj[name[0]] || {};\n obj[name[0]][name[1]] = func;\n } else {\n obj[name[0]] = func; \n }\n};\n\n/**\n * Should create payload from given input args\n *\n * @method toPayload\n * @param {Array} args\n * @return {Object}\n */\nMethod.prototype.toPayload = function (args) {\n var call = this.getCall(args);\n var callback = this.extractCallback(args);\n var params = this.formatInput(args);\n this.validateArgs(params);\n\n return {\n method: call,\n params: params,\n callback: callback\n };\n};\n\n/**\n * Should send request to the API\n *\n * @method send\n * @param list of params\n * @return result\n */\nMethod.prototype.send = function () {\n var payload = this.toPayload(Array.prototype.slice.call(arguments));\n if (payload.callback) {\n var self = this;\n return RequestManager.getInstance().sendAsync(payload, function (err, result) {\n payload.callback(null, self.formatOutput(result));\n });\n }\n return this.formatOutput(RequestManager.getInstance().send(payload));\n};\n\nmodule.exports = Method;\n\n", "/*\n This file is part of ethereum.js.\n\n ethereum.js is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n ethereum.js is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with ethereum.js. If not, see .\n*/\n/** @file eth.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar utils = require('../utils/utils');\nvar Property = require('./property');\n\n/// @returns an array of objects describing web3.eth api methods\nvar methods = [\n];\n\n/// @returns an array of objects describing web3.eth api properties\nvar properties = [\n new Property({\n name: 'listening',\n getter: 'net_listening'\n }),\n new Property({\n name: 'peerCount',\n getter: 'net_peerCount',\n outputFormatter: utils.toDecimal\n })\n];\n\n\nmodule.exports = {\n methods: methods,\n properties: properties\n};\n\n", diff --git a/libjsqrc/ethereumjs/dist/web3.min.js b/libjsqrc/ethereumjs/dist/web3.min.js index 8523f7258..b02f1f966 100644 --- a/libjsqrc/ethereumjs/dist/web3.min.js +++ b/libjsqrc/ethereumjs/dist/web3.min.js @@ -1,2 +1,2 @@ -require=function t(e,n,r){function i(a,s){if(!n[a]){if(!e[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(o)return o(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return i(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;a0&&console.warn("didn't found matching constructor, using default one"),"")};e.exports={inputParser:u,outputParser:c,formatInput:a,formatOutput:s,formatConstructorParams:l}},{"../utils/utils":8,"./coder":2,"./utils":5}],2:[function(t,e,n){var r=t("bignumber.js"),i=t("../utils/utils"),o=t("./formatters"),a=t("./param"),s=function(t){return"[]"===t.slice(-2)},u=function(t){this._name=t.name,this._match=t.match,this._mode=t.mode,this._inputFormatter=t.inputFormatter,this._outputFormatter=t.outputFormatter};u.prototype.isType=function(t){return"strict"===this._match?this._name===t||0===t.indexOf(this._name)&&"[]"===t.slice(this._name.length):"prefix"===this._match?0===t.indexOf(this._name):void 0},u.prototype.formatInput=function(t,e){if(i.isArray(t)&&e){var n=this;return t.map(function(t){return n._inputFormatter(t)}).reduce(function(t,e){return t.appendArrayElement(e),t},new a("",o.formatInputInt(t.length).value))}return this._inputFormatter(t)},u.prototype.formatOutput=function(t,e){if(e){for(var n=[],i=new r(t.prefix,16),o=0;64*i>o;o+=64)n.push(this._outputFormatter(new a(t.suffix.slice(o,o+64))));return n}return this._outputFormatter(t)},u.prototype.isVariadicType=function(t){return s(t)||"bytes"===this._mode},u.prototype.shiftParam=function(t,e){if("bytes"===this._mode)return e.shiftBytes();if(s(t)){var n=new r(e.prefix.slice(0,64),16);return e.shiftArray(n)}return e.shiftValue()};var c=function(t){this._types=t};c.prototype._requireType=function(t){var e=this._types.filter(function(e){return e.isType(t)})[0];if(!e)throw Error("invalid solidity type!: "+t);return e},c.prototype._bytesToParam=function(t,e){var n=this,r=t.reduce(function(t,e){return n._requireType(e).isVariadicType(e)?t+1:t},0),i=t.length-r,o=e.slice(0,64*r);e=e.slice(64*r);var s=e.slice(0,64*i),u=e.slice(64*i);return new a(s,o,u)},c.prototype._formatInput=function(t,e){return this._requireType(t).formatInput(e,s(t))},c.prototype.encodeParam=function(t,e){return this._formatInput(t,e).encode()},c.prototype.encodeParams=function(t,e){var n=this;return t.map(function(t,r){return n._formatInput(t,e[r])}).reduce(function(t,e){return t.append(e),t},new a).encode()},c.prototype._formatOutput=function(t,e){return this._requireType(t).formatOutput(e,s(t))},c.prototype.decodeParam=function(t,e){return this._formatOutput(t,this._bytesToParam([t],e))},c.prototype.decodeParams=function(t,e){var n=this,r=this._bytesToParam(t,e);return t.map(function(t){var e=n._requireType(t),i=e.shiftParam(t,r);return e.formatOutput(i,s(t))})};var l=new c([new u({name:"address",match:"strict",mode:"value",inputFormatter:o.formatInputInt,outputFormatter:o.formatOutputAddress}),new u({name:"bool",match:"strict",mode:"value",inputFormatter:o.formatInputBool,outputFormatter:o.formatOutputBool}),new u({name:"int",match:"prefix",mode:"value",inputFormatter:o.formatInputInt,outputFormatter:o.formatOutputInt}),new u({name:"uint",match:"prefix",mode:"value",inputFormatter:o.formatInputInt,outputFormatter:o.formatOutputUInt}),new u({name:"bytes",match:"strict",mode:"bytes",inputFormatter:o.formatInputDynamicBytes,outputFormatter:o.formatOutputDynamicBytes}),new u({name:"bytes",match:"prefix",mode:"value",inputFormatter:o.formatInputBytes,outputFormatter:o.formatOutputBytes}),new u({name:"real",match:"prefix",mode:"value",inputFormatter:o.formatInputReal,outputFormatter:o.formatOutputReal}),new u({name:"ureal",match:"prefix",mode:"value",inputFormatter:o.formatInputReal,outputFormatter:o.formatOutputUReal})]);e.exports=l},{"../utils/utils":8,"./formatters":3,"./param":4,"bignumber.js":"bignumber.js"}],3:[function(t,e,n){var r=t("bignumber.js"),i=t("../utils/utils"),o=t("../utils/config"),a=t("./param"),s=function(t){var e=2*o.ETH_PADDING;r.config(o.ETH_BIGNUMBER_ROUNDING_MODE);var n=i.padLeft(i.toTwosComplement(t).round().toString(16),e);return new a(n)},u=function(t){var e=i.fromAscii(t,o.ETH_PADDING).substr(2);return new a(e)},c=function(t){var e=i.fromAscii(t,o.ETH_PADDING).substr(2);return new a("",s(t.length).value,e)},l=function(t){var e="000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0");return new a(e)},f=function(t){return s(new r(t).times(new r(2).pow(128)))},p=function(t){return"1"===new r(t.substr(0,1),16).toString(2).substr(0,1)},m=function(t){var e=t.value||"0";return p(e)?new r(e,16).minus(new r("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new r(e,16)},h=function(t){var e=t.value||"0";return new r(e,16)},d=function(t){return m(t).dividedBy(new r(2).pow(128))},g=function(t){return h(t).dividedBy(new r(2).pow(128))},y=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t.value?!0:!1},v=function(t){return i.toAscii(t.value)},b=function(t){return i.toAscii(t.suffix)},w=function(t){var e=t.value;return"0x"+e.slice(e.length-40,e.length)};e.exports={formatInputInt:s,formatInputBytes:u,formatInputDynamicBytes:c,formatInputBool:l,formatInputReal:f,formatOutputInt:m,formatOutputUInt:h,formatOutputReal:d,formatOutputUReal:g,formatOutputBool:y,formatOutputBytes:v,formatOutputDynamicBytes:b,formatOutputAddress:w}},{"../utils/config":7,"../utils/utils":8,"./param":4,"bignumber.js":"bignumber.js"}],4:[function(t,e,n){var r=function(t,e,n){this.prefix=e||"",this.value=t||"",this.suffix=n||""};r.prototype.append=function(t){this.prefix+=t.prefix,this.value+=t.value,this.suffix+=t.suffix},r.prototype.appendArrayElement=function(t){this.suffix+=t.value,this.prefix+=t.prefix},r.prototype.encode=function(){return this.prefix+this.value+this.suffix},r.prototype.shiftValue=function(){var t=this.value.slice(0,64);return this.value=this.value.slice(64),new r(t)},r.prototype.shiftBytes=function(){return this.shiftArray(1)},r.prototype.shiftArray=function(t){var e=this.prefix.slice(0,64);this.prefix=this.value.slice(64);var n=this.suffix.slice(0,64*t);return this.suffix=this.suffix.slice(64*t),new r("",e,n)},e.exports=r},{}],5:[function(t,e,n){var r=function(t,e){return t.filter(function(t){return"constructor"===t.type&&t.inputs.length===e})[0]};e.exports={getConstructor:r}},{}],6:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],7:[function(t,e,n){var r=t("bignumber.js"),i=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:i,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:r.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3,defaultBlock:"latest",defaultAccount:void 0}},{"bignumber.js":"bignumber.js"}],8:[function(t,e,n){var r=t("bignumber.js"),i={wei:"1",kwei:"1000",ada:"1000",mwei:"1000000",babbage:"1000000",gwei:"1000000000",shannon:"1000000000",szabo:"1000000000000",finney:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},o=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},a=function(t){var e="",n=0,r=t.length;for("0x"===t.substring(0,2)&&(n=2);r>n;n+=2){var i=parseInt(t.substr(n,2),16);if(0===i)break;e+=String.fromCharCode(i)}return e},s=function(t){for(var e="",n=0;nthis._inputTypes.length&&o.isObject(t[t.length-1])&&(e=t.pop()),e.to=this._address,e.data="0x"+this.signature()+i.encodeParams(this._inputTypes,t),e},a.prototype.signature=function(){return r.sha3(r.fromAscii(this._name)).slice(2,10)},a.prototype.call=function(){var t=this.toPayload.apply(this,Array.prototype.slice.call(arguments)),e=r.eth.call(t);e=e.length>=2?e.slice(2):e;var n=i.decodeParams(this._outputTypes,e);return 1===n.length?n[0]:n},a.prototype.sendTransaction=function(){var t=this.toPayload.apply(this,Array.prototype.slice.call(arguments));r.eth.sendTransaction(t)},a.prototype.displayName=function(){return o.extractDisplayName(this._name)},a.prototype.typeName=function(){return o.extractTypeName(this._name)},a.prototype.execute=function(){var t=!this._constant;return t?this.sendTransaction.apply(this,Array.prototype.slice.call(arguments)):this.call.apply(this,Array.prototype.slice.call(arguments))},a.prototype.attachToContract=function(t){var e=this.execute.bind(this);e.call=this.call.bind(this),e.sendTransaction=this.sendTransaction.bind(this);var n=this.displayName();t[n]||(t[n]=e),t[n][this.typeName()]=e},e.exports=a},{"../solidity/coder":2,"../utils/utils":8,"../web3":10}],19:[function(t,e,n){"use strict";var r=t("xmlhttprequest").XMLHttpRequest,i=t("./errors"),o=function(t){this.host=t||"http://localhost:8545"};o.prototype.send=function(t){var e=new r;e.open("POST",this.host,!1);try{e.send(JSON.stringify(t))}catch(n){throw i.InvalidConnection(this.host)}return JSON.parse(e.responseText)},o.prototype.sendAsync=function(t,e){var n=new r;n.onreadystatechange=function(){4===n.readyState&&e(null,JSON.parse(n.responseText))},n.open("POST",this.host,!0);try{n.send(JSON.stringify(t))}catch(o){e(i.InvalidConnection(this.host))}},e.exports=o},{"./errors":13,xmlhttprequest:6}],20:[function(t,e,n){var r=function(){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,void(this.messageId=1))};r.getInstance=function(){var t=new r;return t},r.prototype.toPayload=function(t,e){return t||console.error("jsonrpc method should be specified!"),{jsonrpc:"2.0",method:t,params:e||[],id:this.messageId++}},r.prototype.isValidResponse=function(t){return!!t&&!t.error&&"2.0"===t.jsonrpc&&"number"==typeof t.id&&void 0!==t.result},r.prototype.toBatchPayload=function(t){var e=this;return t.map(function(t){return e.toPayload(t.method,t.params)})},e.exports=r},{}],21:[function(t,e,n){var r=t("./requestmanager"),i=t("../utils/utils"),o=t("./errors"),a=function(t){this.name=t.name,this.call=t.call,this.params=t.params||0,this.inputFormatter=t.inputFormatter,this.outputFormatter=t.outputFormatter};a.prototype.getCall=function(t){return i.isFunction(this.call)?this.call(t):this.call},a.prototype.extractCallback=function(t){return i.isFunction(t[t.length-1])?t.pop():null},a.prototype.validateArgs=function(t){if(t.length!==this.params)throw o.InvalidNumberOfParams()},a.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter.map(function(e,n){return e?e(t[n]):t[n]}):t},a.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},a.prototype.attachToObject=function(t){var e=this.send.bind(this);e.call=this.call;var n=this.name.split(".");n.length>1?(t[n[0]]=t[n[0]]||{},t[n[0]][n[1]]=e):t[n[0]]=e},a.prototype.toPayload=function(t){var e=this.getCall(t),n=this.extractCallback(t),r=this.formatInput(t);return this.validateArgs(r),{method:e,params:r,callback:n}},a.prototype.send=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));if(t.callback){var e=this;return r.getInstance().sendAsync(t,function(n,r){t.callback(null,e.formatOutput(r))})}return this.formatOutput(r.getInstance().send(t))},e.exports=a},{"../utils/utils":8,"./errors":13,"./requestmanager":25}],22:[function(t,e,n){var r=t("../utils/utils"),i=t("./property"),o=[],a=[new i({name:"listening",getter:"net_listening"}),new i({name:"peerCount",getter:"net_peerCount",outputFormatter:r.toDecimal})];e.exports={methods:o,properties:a}},{"../utils/utils":8,"./property":23}],23:[function(t,e,n){var r=t("./requestmanager"),i=function(t){this.name=t.name,this.getter=t.getter,this.setter=t.setter,this.outputFormatter=t.outputFormatter,this.inputFormatter=t.inputFormatter};i.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter(t):t},i.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},i.prototype.attachToObject=function(t){var e={get:this.get.bind(this),set:this.set.bind(this)},n=this.name.split(".");n.length>1?(t[n[0]]=t[n[0]]||{},Object.defineProperty(t[n[0]],n[1],e)):Object.defineProperty(t,n[0],e)},i.prototype.get=function(){return this.formatOutput(r.getInstance().send({method:this.getter}))},i.prototype.set=function(t){return r.getInstance().send({method:this.setter,params:[this.formatInput(t)]})},e.exports=i},{"./requestmanager":25}],24:[function(t,e,n){var r=function(){};r.prototype.send=function(t){var e=navigator.qt.callMethod(JSON.stringify(t));return JSON.parse(e)},e.exports=r},{}],25:[function(t,e,n){var r=t("./jsonrpc"),i=t("../utils/utils"),o=t("../utils/config"),a=t("./errors"),s=function(t){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,this.provider=t,this.polls=[],this.timeout=null,void this.poll())};s.getInstance=function(){var t=new s;return t},s.prototype.send=function(t){if(!this.provider)return console.error(a.InvalidProvider()),null;var e=r.getInstance().toPayload(t.method,t.params),n=this.provider.send(e);if(!r.getInstance().isValidResponse(n))throw a.InvalidResponse(n);return n.result},s.prototype.sendAsync=function(t,e){if(!this.provider)return e(a.InvalidProvider());var n=r.getInstance().toPayload(t.method,t.params);this.provider.sendAsync(n,function(t,n){return t?e(t):r.getInstance().isValidResponse(n)?void e(null,n.result):e(a.InvalidResponse(n))})},s.prototype.setProvider=function(t){this.provider=t},s.prototype.startPolling=function(t,e,n,r){this.polls.push({data:t,id:e,callback:n,uninstall:r})},s.prototype.stopPolling=function(t){for(var e=this.polls.length;e--;){var n=this.polls[e];n.id===t&&this.polls.splice(e,1)}},s.prototype.reset=function(){this.polls.forEach(function(t){t.uninstall(t.id)}),this.polls=[],this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.poll()},s.prototype.poll=function(){if(this.timeout=setTimeout(this.poll.bind(this),o.ETH_POLLING_TIMEOUT),this.polls.length){if(!this.provider)return void console.error(a.InvalidProvider());var t=r.getInstance().toBatchPayload(this.polls.map(function(t){return t.data})),e=this;this.provider.sendAsync(t,function(t,n){if(!t){if(!i.isArray(n))throw a.InvalidResponse(n);n.map(function(t,n){return t.callback=e.polls[n].callback,t}).filter(function(t){var e=r.getInstance().isValidResponse(t);return e||t.callback(a.InvalidResponse(t)),e}).filter(function(t){return i.isArray(t.result)&&t.result.length>0}).forEach(function(t){t.callback(null,t.result)})}})}},e.exports=s},{"../utils/config":7,"../utils/utils":8,"./errors":13,"./jsonrpc":20}],26:[function(t,e,n){var r=t("./method"),i=t("./formatters"),o=new r({name:"post",call:"shh_post",params:1,inputFormatter:[i.inputPostFormatter]}),a=new r({name:"newIdentity",call:"shh_newIdentity",params:0}),s=new r({name:"hasIdentity",call:"shh_hasIdentity",params:1}),u=new r({name:"newGroup",call:"shh_newGroup",params:0}),c=new r({name:"addToGroup",call:"shh_addToGroup",params:0}),l=[o,a,s,u,c];e.exports={methods:l}},{"./formatters":17,"./method":21}],27:[function(t,e,n){var r=t("./method"),i=function(){var t=function(t){return"string"==typeof t[0]?"eth_newBlockFilter":"eth_newFilter"},e=new r({name:"newFilter",call:t,params:1}),n=new r({name:"uninstallFilter",call:"eth_uninstallFilter",params:1}),i=new r({name:"getLogs",call:"eth_getFilterLogs",params:1}),o=new r({name:"poll",call:"eth_getFilterChanges",params:1 -});return[e,n,i,o]},o=function(){var t=new r({name:"newFilter",call:"shh_newFilter",params:1}),e=new r({name:"uninstallFilter",call:"shh_uninstallFilter",params:1}),n=new r({name:"getLogs",call:"shh_getMessages",params:1}),i=new r({name:"poll",call:"shh_getFilterChanges",params:1});return[t,e,n,i]};e.exports={eth:i,shh:o}},{"./method":21}],28:[function(t,e,n){},{}],"bignumber.js":[function(t,e,n){!function(n){"use strict";function r(t){function e(t,r){var i,o,a,s,u,c,l=this;if(!(l instanceof e))return V&&k(26,"constructor call without new",t),new e(t,r);if(null!=r&&J(r,2,64,R,"base")){if(r=0|r,c=t+"",10==r)return l=new e(t instanceof e?t:c),E(l,j+l.e+1,U);if((s="number"==typeof t)&&0*t!=0||!new RegExp("^-?"+(i="["+_.slice(0,r)+"]+")+"(?:\\."+i+")?$",37>r?"i":"").test(c))return d(l,c,s,r);s?(l.s=0>1/t?(c=c.slice(1),-1):1,V&&c.replace(/^0\.0*|\./,"").length>15&&k(R,x,t),s=!1):l.s=45===c.charCodeAt(0)?(c=c.slice(1),-1):1,c=n(c,10,r,l.s)}else{if(t instanceof e)return l.s=t.s,l.e=t.e,l.c=(t=t.c)?t.slice():t,void(R=0);if((s="number"==typeof t)&&0*t==0){if(l.s=0>1/t?(t=-t,-1):1,t===~~t){for(o=0,a=t;a>=10;a/=10,o++);return l.e=o,l.c=[t],void(R=0)}c=t+""}else{if(!g.test(c=t+""))return d(l,c,s);l.s=45===c.charCodeAt(0)?(c=c.slice(1),-1):1}}for((o=c.indexOf("."))>-1&&(c=c.replace(".","")),(a=c.search(/e/i))>0?(0>o&&(o=a),o+=+c.slice(a+1),c=c.substring(0,a)):0>o&&(o=c.length),a=0;48===c.charCodeAt(a);a++);for(u=c.length;48===c.charCodeAt(--u););if(c=c.slice(a,u+1))if(u=c.length,s&&V&&u>15&&k(R,x,l.s*t),o=o-a-1,o>G)l.c=l.e=null;else if(M>o)l.c=[l.e=0];else{if(l.e=o,l.c=[],a=(o+1)%N,0>o&&(a+=N),u>a){for(a&&l.c.push(+c.slice(0,a)),u-=N;u>a;)l.c.push(+c.slice(a,a+=N));c=c.slice(a),a=N-c.length}else a-=u;for(;a--;c+="0");l.c.push(+c)}else l.c=[l.e=0];R=0}function n(t,n,r,i){var a,s,u,l,p,m,h,d=t.indexOf("."),g=j,y=U;for(37>r&&(t=t.toLowerCase()),d>=0&&(u=z,z=0,t=t.replace(".",""),h=new e(r),p=h.pow(t.length-d),z=u,h.c=c(f(o(p.c),p.e),10,n),h.e=h.c.length),m=c(t,r,n),s=u=m.length;0==m[--u];m.pop());if(!m[0])return"0";if(0>d?--s:(p.c=m,p.e=s,p.s=i,p=S(p,h,g,y,n),m=p.c,l=p.r,s=p.e),a=s+g+1,d=m[a],u=n/2,l=l||0>a||null!=m[a+1],l=4>y?(null!=d||l)&&(0==y||y==(p.s<0?3:2)):d>u||d==u&&(4==y||l||6==y&&1&m[a-1]||y==(p.s<0?8:7)),1>a||!m[0])t=l?f("1",-g):"0";else{if(m.length=a,l)for(--n;++m[--a]>n;)m[a]=0,a||(++s,m.unshift(1));for(u=m.length;!m[--u];);for(d=0,t="";u>=d;t+=_.charAt(m[d++]));t=f(t,s)}return t}function m(t,n,r,i){var a,s,u,c,p;if(r=null!=r&&J(r,0,8,i,w)?0|r:U,!t.c)return t.toString();if(a=t.c[0],u=t.e,null==n)p=o(t.c),p=19==i||24==i&&H>=u?l(p,u):f(p,u);else if(t=E(new e(t),n,r),s=t.e,p=o(t.c),c=p.length,19==i||24==i&&(s>=n||H>=s)){for(;n>c;p+="0",c++);p=l(p,s)}else if(n-=u,p=f(p,s),s+1>c){if(--n>0)for(p+=".";n--;p+="0");}else if(n+=s-c,n>0)for(s+1==c&&(p+=".");n--;p+="0");return t.s<0&&a?"-"+p:p}function A(t,n){var r,i,o=0;for(u(t[0])&&(t=t[0]),r=new e(t[0]);++ot||t>n||t!=p(t))&&k(r,(i||"decimal places")+(e>t||t>n?" out of range":" not an integer"),t),!0}function P(t,e,n){for(var r=1,i=e.length;!e[--i];e.pop());for(i=e[0];i>=10;i/=10,r++);return(n=r+n*N-1)>G?t.c=t.e=null:M>n?t.c=[t.e=0]:(t.e=n,t.c=e),t}function k(t,e,n){var r=new Error(["new BigNumber","cmp","config","div","divToInt","eq","gt","gte","lt","lte","minus","mod","plus","precision","random","round","shift","times","toDigits","toExponential","toFixed","toFormat","toFraction","pow","toPrecision","toString","BigNumber"][t]+"() "+e+": "+n);throw r.name="BigNumber Error",R=0,r}function E(t,e,n,r){var i,o,a,s,u,c,l,f=t.c,p=O;if(f){t:{for(i=1,s=f[0];s>=10;s/=10,i++);if(o=e-i,0>o)o+=N,a=e,u=f[c=0],l=u/p[i-a-1]%10|0;else if(c=y((o+1)/N),c>=f.length){if(!r)break t;for(;f.length<=c;f.push(0));u=l=0,i=1,o%=N,a=o-N+1}else{for(u=s=f[c],i=1;s>=10;s/=10,i++);o%=N,a=o-N+i,l=0>a?0:u/p[i-a-1]%10|0}if(r=r||0>e||null!=f[c+1]||(0>a?u:u%p[i-a-1]),r=4>n?(l||r)&&(0==n||n==(t.s<0?3:2)):l>5||5==l&&(4==n||r||6==n&&(o>0?a>0?u/p[i-a]:0:f[c-1])%10&1||n==(t.s<0?8:7)),1>e||!f[0])return f.length=0,r?(e-=t.e+1,f[0]=p[e%N],t.e=-e||0):f[0]=t.e=0,t;if(0==o?(f.length=c,s=1,c--):(f.length=c+1,s=p[N-o],f[c]=a>0?v(u/p[i-a]%p[a])*s:0),r)for(;;){if(0==c){for(o=1,a=f[0];a>=10;a/=10,o++);for(a=f[0]+=s,s=1;a>=10;a/=10,s++);o!=s&&(t.e++,f[0]==F&&(f[0]=1));break}if(f[c]+=s,f[c]!=F)break;f[c--]=0,s=1}for(o=f.length;0===f[--o];f.pop());}t.e>G?t.c=t.e=null:t.en?null!=(t=i[n++]):void 0};return a(e="DECIMAL_PLACES")&&J(t,0,B,2,e)&&(j=0|t),r[e]=j,a(e="ROUNDING_MODE")&&J(t,0,8,2,e)&&(U=0|t),r[e]=U,a(e="EXPONENTIAL_AT")&&(u(t)?J(t[0],-B,0,2,e)&&J(t[1],0,B,2,e)&&(H=0|t[0],q=0|t[1]):J(t,-B,B,2,e)&&(H=-(q=0|(0>t?-t:t)))),r[e]=[H,q],a(e="RANGE")&&(u(t)?J(t[0],-B,-1,2,e)&&J(t[1],1,B,2,e)&&(M=0|t[0],G=0|t[1]):J(t,-B,B,2,e)&&(0|t?M=-(G=0|(0>t?-t:t)):V&&k(2,e+" cannot be zero",t))),r[e]=[M,G],a(e="ERRORS")&&(t===!!t||1===t||0===t?(R=0,J=(V=!!t)?D:s):V&&k(2,e+b,t)),r[e]=V,a(e="CRYPTO")&&(t===!!t||1===t||0===t?(W=!(!t||!h||"object"!=typeof h),t&&!W&&V&&k(2,"crypto unavailable",h)):V&&k(2,e+b,t)),r[e]=W,a(e="MODULO_MODE")&&J(t,0,9,2,e)&&($=0|t),r[e]=$,a(e="POW_PRECISION")&&J(t,0,B,2,e)&&(z=0|t),r[e]=z,a(e="FORMAT")&&("object"==typeof t?X=t:V&&k(2,e+" not an object",t)),r[e]=X,r},e.max=function(){return A(arguments,C.lt)},e.min=function(){return A(arguments,C.gt)},e.random=function(){var t=9007199254740992,n=Math.random()*t&2097151?function(){return v(Math.random()*t)}:function(){return 8388608*(1073741824*Math.random()|0)+(8388608*Math.random()|0)};return function(t){var r,i,o,a,s,u=0,c=[],l=new e(L);if(t=null!=t&&J(t,0,B,14)?0|t:j,a=y(t/N),W)if(h&&h.getRandomValues){for(r=h.getRandomValues(new Uint32Array(a*=2));a>u;)s=131072*r[u]+(r[u+1]>>>11),s>=9e15?(i=h.getRandomValues(new Uint32Array(2)),r[u]=i[0],r[u+1]=i[1]):(c.push(s%1e14),u+=2);u=a/2}else if(h&&h.randomBytes){for(r=h.randomBytes(a*=7);a>u;)s=281474976710656*(31&r[u])+1099511627776*r[u+1]+4294967296*r[u+2]+16777216*r[u+3]+(r[u+4]<<16)+(r[u+5]<<8)+r[u+6],s>=9e15?h.randomBytes(7).copy(r,u):(c.push(s%1e14),u+=7);u=a/7}else V&&k(14,"crypto unavailable",h);if(!u)for(;a>u;)s=n(),9e15>s&&(c[u++]=s%1e14);for(a=c[--u],t%=N,a&&t&&(s=O[N-t],c[u]=v(a/s)*s);0===c[u];c.pop(),u--);if(0>u)c=[o=0];else{for(o=-1;0===c[0];c.shift(),o-=N);for(u=1,s=c[0];s>=10;s/=10,u++);N>u&&(o-=N-u)}return l.e=o,l.c=c,l}}(),S=function(){function t(t,e,n){var r,i,o,a,s=0,u=t.length,c=e%T,l=e/T|0;for(t=t.slice();u--;)o=t[u]%T,a=t[u]/T|0,r=l*o+a*c,i=c*o+r%T*T+s,s=(i/n|0)+(r/T|0)+l*a,t[u]=i%n;return s&&t.unshift(s),t}function n(t,e,n,r){var i,o;if(n!=r)o=n>r?1:-1;else for(i=o=0;n>i;i++)if(t[i]!=e[i]){o=t[i]>e[i]?1:-1;break}return o}function r(t,e,n,r){for(var i=0;n--;)t[n]-=i,i=t[n]1;t.shift());}return function(o,a,s,u,c){var l,f,p,m,h,d,g,y,b,w,x,_,I,O,T,B,A,D=o.s==a.s?1:-1,P=o.c,k=a.c;if(!(P&&P[0]&&k&&k[0]))return new e(o.s&&a.s&&(P?!k||P[0]!=k[0]:k)?P&&0==P[0]||!k?0*D:D/0:0/0);for(y=new e(D),b=y.c=[],f=o.e-a.e,D=s+f+1,c||(c=F,f=i(o.e/N)-i(a.e/N),D=D/N|0),p=0;k[p]==(P[p]||0);p++);if(k[p]>(P[p]||0)&&f--,0>D)b.push(1),m=!0;else{for(O=P.length,B=k.length,p=0,D+=2,h=v(c/(k[0]+1)),h>1&&(k=t(k,h,c),P=t(P,h,c),B=k.length,O=P.length),I=B,w=P.slice(0,B),x=w.length;B>x;w[x++]=0);A=k.slice(),A.unshift(0),T=k[0],k[1]>=c/2&&T++;do{if(h=0,l=n(k,w,B,x),0>l){if(_=w[0],B!=x&&(_=_*c+(w[1]||0)),h=v(_/T),h>1)for(h>=c&&(h=c-1),d=t(k,h,c),g=d.length,x=w.length;1==n(d,w,g,x);)h--,r(d,g>B?A:k,g,c),g=d.length,l=1;else 0==h&&(l=h=1),d=k.slice(),g=d.length;if(x>g&&d.unshift(0),r(w,d,x,c),x=w.length,-1==l)for(;n(k,w,B,x)<1;)h++,r(w,x>B?A:k,x,c),x=w.length}else 0===l&&(h++,w=[0]);b[p++]=h,w[0]?w[x++]=P[I]||0:(w=[P[I]],x=1)}while((I++=10;D/=10,p++);E(y,s+(y.e=p+f*N-1)+1,u,m)}else y.e=f,y.r=+m;return y}}(),d=function(){var t=/^(-?)0([xbo])/i,n=/^([^.]+)\.$/,r=/^\.([^.]+)$/,i=/^-?(Infinity|NaN)$/,o=/^\s*\+|^\s+|\s+$/g;return function(a,s,u,c){var l,f=u?s:s.replace(o,"");if(i.test(f))a.s=isNaN(f)?null:0>f?-1:1;else{if(!u&&(f=f.replace(t,function(t,e,n){return l="x"==(n=n.toLowerCase())?16:"b"==n?2:8,c&&c!=l?t:e}),c&&(l=c,f=f.replace(n,"$1").replace(r,"0.$1")),s!=f))return new e(f,l);V&&k(R,"not a"+(c?" base "+c:"")+" number",s),a.s=null}a.c=a.e=null,R=0}}(),C.absoluteValue=C.abs=function(){var t=new e(this);return t.s<0&&(t.s=1),t},C.ceil=function(){return E(new e(this),this.e+1,2)},C.comparedTo=C.cmp=function(t,n){return R=1,a(this,new e(t,n))},C.decimalPlaces=C.dp=function(){var t,e,n=this.c;if(!n)return null;if(t=((e=n.length-1)-i(this.e/N))*N,e=n[e])for(;e%10==0;e/=10,t--);return 0>t&&(t=0),t},C.dividedBy=C.div=function(t,n){return R=3,S(this,new e(t,n),j,U)},C.dividedToIntegerBy=C.divToInt=function(t,n){return R=4,S(this,new e(t,n),0,1)},C.equals=C.eq=function(t,n){return R=5,0===a(this,new e(t,n))},C.floor=function(){return E(new e(this),this.e+1,3)},C.greaterThan=C.gt=function(t,n){return R=6,a(this,new e(t,n))>0},C.greaterThanOrEqualTo=C.gte=function(t,n){return R=7,1===(n=a(this,new e(t,n)))||0===n},C.isFinite=function(){return!!this.c},C.isInteger=C.isInt=function(){return!!this.c&&i(this.e/N)>this.c.length-2},C.isNaN=function(){return!this.s},C.isNegative=C.isNeg=function(){return this.s<0},C.isZero=function(){return!!this.c&&0==this.c[0]},C.lessThan=C.lt=function(t,n){return R=8,a(this,new e(t,n))<0},C.lessThanOrEqualTo=C.lte=function(t,n){return R=9,-1===(n=a(this,new e(t,n)))||0===n},C.minus=C.sub=function(t,n){var r,o,a,s,u=this,c=u.s;if(R=10,t=new e(t,n),n=t.s,!c||!n)return new e(0/0);if(c!=n)return t.s=-n,u.plus(t);var l=u.e/N,f=t.e/N,p=u.c,m=t.c;if(!l||!f){if(!p||!m)return p?(t.s=-n,t):new e(m?u:0/0);if(!p[0]||!m[0])return m[0]?(t.s=-n,t):new e(p[0]?u:3==U?-0:0)}if(l=i(l),f=i(f),p=p.slice(),c=l-f){for((s=0>c)?(c=-c,a=p):(f=l,a=m),a.reverse(),n=c;n--;a.push(0));a.reverse()}else for(o=(s=(c=p.length)<(n=m.length))?c:n,c=n=0;o>n;n++)if(p[n]!=m[n]){s=p[n]0)for(;n--;p[r++]=0);for(n=F-1;o>c;){if(p[--o]0?(u=s,r=l):(a=-a,r=c),r.reverse();a--;r.push(0));r.reverse()}for(a=c.length,n=l.length,0>a-n&&(r=l,l=c,c=r,n=a),a=0;n;)a=(c[--n]=c[n]+l[n]+a)/F|0,c[n]%=F;return a&&(c.unshift(a),++u),P(t,c,u)},C.precision=C.sd=function(t){var e,n,r=this,i=r.c;if(null!=t&&t!==!!t&&1!==t&&0!==t&&(V&&k(13,"argument"+b,t),t!=!!t&&(t=null)),!i)return null;if(n=i.length-1,e=n*N+1,n=i[n]){for(;n%10==0;n/=10,e--);for(n=i[0];n>=10;n/=10,e++);}return t&&r.e+1>e&&(e=r.e+1),e},C.round=function(t,n){var r=new e(this);return(null==t||J(t,0,B,15))&&E(r,~~t+this.e+1,null!=n&&J(n,0,8,15,w)?0|n:U),r},C.shift=function(t){var n=this;return J(t,-I,I,16,"argument")?n.times("1e"+p(t)):new e(n.c&&n.c[0]&&(-I>t||t>I)?n.s*(0>t?0:1/0):n)},C.squareRoot=C.sqrt=function(){var t,n,r,a,s,u=this,c=u.c,l=u.s,f=u.e,p=j+4,m=new e("0.5");if(1!==l||!c||!c[0])return new e(!l||0>l&&(!c||c[0])?0/0:c?u:1/0);if(l=Math.sqrt(+u),0==l||l==1/0?(n=o(c),(n.length+f)%2==0&&(n+="0"),l=Math.sqrt(n),f=i((f+1)/2)-(0>f||f%2),l==1/0?n="1e"+f:(n=l.toExponential(),n=n.slice(0,n.indexOf("e")+1)+f),r=new e(n)):r=new e(l+""),r.c[0])for(f=r.e,l=f+p,3>l&&(l=0);;)if(s=r,r=m.times(s.plus(S(u,s,p,1))),o(s.c).slice(0,l)===(n=o(r.c)).slice(0,l)){if(r.el&&(g=w,w=x,x=g,a=l,l=m,m=a),a=l+m,g=[];a--;g.push(0));for(y=F,v=T,a=m;--a>=0;){for(r=0,h=x[a]%v,d=x[a]/v|0,u=l,s=a+u;s>a;)f=w[--u]%v,p=w[u]/v|0,c=d*f+p*h,f=h*f+c%v*v+g[s]+r,r=(f/y|0)+(c/v|0)+d*p,g[s--]=f%y;g[s]=r}return r?++o:g.shift(),P(t,g,o)},C.toDigits=function(t,n){var r=new e(this);return t=null!=t&&J(t,1,B,18,"precision")?0|t:null,n=null!=n&&J(n,0,8,18,w)?0|n:U,t?E(r,t,n):r},C.toExponential=function(t,e){return m(this,null!=t&&J(t,0,B,19)?~~t+1:null,e,19)},C.toFixed=function(t,e){return m(this,null!=t&&J(t,0,B,20)?~~t+this.e+1:null,e,20)},C.toFormat=function(t,e){var n=m(this,null!=t&&J(t,0,B,21)?~~t+this.e+1:null,e,21);if(this.c){var r,i=n.split("."),o=+X.groupSize,a=+X.secondaryGroupSize,s=X.groupSeparator,u=i[0],c=i[1],l=this.s<0,f=l?u.slice(1):u,p=f.length;if(a&&(r=o,o=a,a=r,p-=r),o>0&&p>0){for(r=p%o||o,u=f.substr(0,r);p>r;r+=o)u+=s+f.substr(r,o);a>0&&(u+=s+f.slice(r)),l&&(u="-"+u)}n=c?u+X.decimalSeparator+((a=+X.fractionGroupSize)?c.replace(new RegExp("\\d{"+a+"}\\B","g"),"$&"+X.fractionGroupSeparator):c):u}return n},C.toFraction=function(t){var n,r,i,a,s,u,c,l,f,p=V,m=this,h=m.c,d=new e(L),g=r=new e(L),y=c=new e(L);if(null!=t&&(V=!1,u=new e(t),V=p,(!(p=u.isInt())||u.lt(L))&&(V&&k(22,"max denominator "+(p?"out of range":"not an integer"),t),t=!p&&u.c&&E(u,u.e+1,1).gte(L)?u:null)),!h)return m.toString();for(f=o(h),a=d.e=f.length-m.e-1,d.c[0]=O[(s=a%N)<0?N+s:s],t=!t||u.cmp(d)>0?a>0?d:g:u,s=G,G=1/0,u=new e(f),c.c[0]=0;l=S(u,d,0,1),i=r.plus(l.times(y)),1!=i.cmp(t);)r=y,y=i,g=c.plus(l.times(i=g)),c=i,d=u.minus(l.times(i=d)),u=i;return i=S(t.minus(r),y,0,1),c=c.plus(i.times(g)),r=r.plus(i.times(y)),c.s=g.s=m.s,a*=2,n=S(g,y,a,U).minus(m).abs().cmp(S(c,r,a,U).minus(m).abs())<1?[g.toString(),y.toString()]:[c.toString(),r.toString()],G=s,n},C.toNumber=function(){var t=this;return+t||(t.s?0*t.s:0/0)},C.toPower=C.pow=function(t){var n,r,i=v(0>t?-t:+t),o=this;if(!J(t,-I,I,23,"exponent")&&(!isFinite(t)||i>I&&(t/=0)||parseFloat(t)!=t&&!(t=0/0)))return new e(Math.pow(+o,t));for(n=z?y(z/N+2):0,r=new e(L);;){if(i%2){if(r=r.times(o),!r.c)break;n&&r.c.length>n&&(r.c.length=n)}if(i=v(i/2),!i)break;o=o.times(o),n&&o.c&&o.c.length>n&&(o.c.length=n)}return 0>t&&(r=L.div(r)),n?E(r,z,U):r},C.toPrecision=function(t,e){return m(this,null!=t&&J(t,1,B,24,"precision")?0|t:null,e,24)},C.toString=function(t){var e,r=this,i=r.s,a=r.e;return null===a?i?(e="Infinity",0>i&&(e="-"+e)):e="NaN":(e=o(r.c),e=null!=t&&J(t,2,64,25,"base")?n(f(e,a),0|t,10,i):H>=a||a>=q?l(e,a):f(e,a),0>i&&r.c[0]&&(e="-"+e)),e},C.truncated=C.trunc=function(){return E(new e(this),this.e+1,1)},C.valueOf=C.toJSON=function(){return this.toString()},null!=t&&e.config(t),e}function i(t){var e=0|t;return t>0||t===e?e:e-1}function o(t){for(var e,n,r=1,i=t.length,o=t[0]+"";i>r;){for(e=t[r++]+"",n=N-e.length;n--;e="0"+e);o+=e}for(i=o.length;48===o.charCodeAt(--i););return o.slice(0,i+1||1)}function a(t,e){var n,r,i=t.c,o=e.c,a=t.s,s=e.s,u=t.e,c=e.e;if(!a||!s)return null;if(n=i&&!i[0],r=o&&!o[0],n||r)return n?r?0:-s:a;if(a!=s)return a;if(n=0>a,r=u==c,!i||!o)return r?0:!i^n?1:-1;if(!r)return u>c^n?1:-1;for(s=(u=i.length)<(c=o.length)?u:c,a=0;s>a;a++)if(i[a]!=o[a])return i[a]>o[a]^n?1:-1;return u==c?0:u>c^n?1:-1}function s(t,e,n){return(t=p(t))>=e&&n>=t}function u(t){return"[object Array]"==Object.prototype.toString.call(t)}function c(t,e,n){for(var r,i,o=[0],a=0,s=t.length;s>a;){for(i=o.length;i--;o[i]*=e);for(o[r=0]+=_.indexOf(t.charAt(a++));rn-1&&(null==o[r+1]&&(o[r+1]=0),o[r+1]+=o[r]/n|0,o[r]%=n)}return o.reverse()}function l(t,e){return(t.length>1?t.charAt(0)+"."+t.slice(1):t)+(0>e?"e":"e+")+e}function f(t,e){var n,r;if(0>e){for(r="0.";++e;r+="0");t=r+t}else if(n=t.length,++e>n){for(r="0",e-=n;--e;r+="0");t+=r}else n>e&&(t=t.slice(0,e)+"."+t.slice(e));return t}function p(t){return t=parseFloat(t),0>t?y(t):v(t)}var m,h,d,g=/^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,y=Math.ceil,v=Math.floor,b=" not a boolean or binary digit",w="rounding mode",x="number type has more than 15 significant digits",_="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_",F=1e14,N=14,I=9007199254740991,O=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],T=1e7,B=1e9;if(m=r(),"function"==typeof define&&define.amd)define(function(){return m});else if("undefined"!=typeof e&&e.exports){if(e.exports=m,!h)try{h=t("crypto")}catch(A){}}else n.BigNumber=m}(this)},{crypto:28}],web3:[function(t,e,n){var r=t("./lib/web3");r.providers.HttpProvider=t("./lib/web3/httpprovider"),r.providers.QtSyncProvider=t("./lib/web3/qtsync"),r.eth.contract=t("./lib/web3/contract"),r.abi=t("./lib/solidity/abi"),"undefined"!=typeof window&&"undefined"==typeof window.web3&&(window.web3=r),e.exports=r},{"./lib/solidity/abi":1,"./lib/web3":10,"./lib/web3/contract":11,"./lib/web3/httpprovider":19,"./lib/web3/qtsync":24}]},{},["web3"]); \ No newline at end of file +require=function t(e,n,r){function o(a,s){if(!n[a]){if(!e[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[a]={exports:{}};e[a][0].call(l.exports,function(t){var n=e[a][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;a0&&console.warn("didn't found matching constructor, using default one"),"")};e.exports={formatConstructorParams:i}},{"./coder":2,"./utils":5}],2:[function(t,e,n){var r=t("bignumber.js"),o=t("../utils/utils"),i=t("./formatters"),a=t("./param"),s=function(t){return"[]"===t.slice(-2)},u=function(t){this._name=t.name,this._match=t.match,this._mode=t.mode,this._inputFormatter=t.inputFormatter,this._outputFormatter=t.outputFormatter};u.prototype.isType=function(t){return"strict"===this._match?this._name===t||0===t.indexOf(this._name)&&"[]"===t.slice(this._name.length):"prefix"===this._match?0===t.indexOf(this._name):void 0},u.prototype.formatInput=function(t,e){if(o.isArray(t)&&e){var n=this;return t.map(function(t){return n._inputFormatter(t)}).reduce(function(t,e){return t.combine(e)},i.formatInputInt(t.length)).withOffset(32)}return this._inputFormatter(t)},u.prototype.formatOutput=function(t,e){if(e){for(var n=[],o=new r(t.dynamicPart().slice(0,64),16),i=0;64*o>i;i+=64)n.push(this._outputFormatter(new a(t.dynamicPart().substr(i+64,64))));return n}return this._outputFormatter(t)},u.prototype.sliceParam=function(t,e,n){return"bytes"===this._mode?a.decodeBytes(t,e):s(n)?a.decodeArray(t,e):a.decodeParam(t,e)};var c=function(t){this._types=t};c.prototype._requireType=function(t){var e=this._types.filter(function(e){return e.isType(t)})[0];if(!e)throw Error("invalid solidity type!: "+t);return e},c.prototype._formatInput=function(t,e){return this._requireType(t).formatInput(e,s(t))},c.prototype.encodeParam=function(t,e){return this._formatInput(t,e).encode()},c.prototype.encodeParams=function(t,e){var n=this,r=t.map(function(t,r){return n._formatInput(t,e[r])});return a.encodeList(r)},c.prototype.decodeParam=function(t,e){return this.decodeParams([t],e)[0]},c.prototype.decodeParams=function(t,e){var n=this;return t.map(function(t,r){var o=n._requireType(t),i=o.sliceParam(e,r,t);return o.formatOutput(i,s(t))})};var l=new c([new u({name:"address",match:"strict",mode:"value",inputFormatter:i.formatInputInt,outputFormatter:i.formatOutputAddress}),new u({name:"bool",match:"strict",mode:"value",inputFormatter:i.formatInputBool,outputFormatter:i.formatOutputBool}),new u({name:"int",match:"prefix",mode:"value",inputFormatter:i.formatInputInt,outputFormatter:i.formatOutputInt}),new u({name:"uint",match:"prefix",mode:"value",inputFormatter:i.formatInputInt,outputFormatter:i.formatOutputUInt}),new u({name:"bytes",match:"strict",mode:"bytes",inputFormatter:i.formatInputDynamicBytes,outputFormatter:i.formatOutputDynamicBytes}),new u({name:"bytes",match:"prefix",mode:"value",inputFormatter:i.formatInputBytes,outputFormatter:i.formatOutputBytes}),new u({name:"real",match:"prefix",mode:"value",inputFormatter:i.formatInputReal,outputFormatter:i.formatOutputReal}),new u({name:"ureal",match:"prefix",mode:"value",inputFormatter:i.formatInputReal,outputFormatter:i.formatOutputUReal})]);e.exports=l},{"../utils/utils":8,"./formatters":3,"./param":4,"bignumber.js":"bignumber.js"}],3:[function(t,e,n){var r=t("bignumber.js"),o=t("../utils/utils"),i=t("../utils/config"),a=t("./param"),s=function(t){var e=2*i.ETH_PADDING;r.config(i.ETH_BIGNUMBER_ROUNDING_MODE);var n=o.padLeft(o.toTwosComplement(t).round().toString(16),e);return new a(n)},u=function(t){var e=o.fromAscii(t,i.ETH_PADDING).substr(2);return new a(e)},c=function(t){var e=o.fromAscii(t,i.ETH_PADDING).substr(2);return new a(s(t.length).value+e,32)},l=function(t){var e="000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0");return new a(e)},f=function(t){return s(new r(t).times(new r(2).pow(128)))},p=function(t){return"1"===new r(t.substr(0,1),16).toString(2).substr(0,1)},m=function(t){var e=t.staticPart()||"0";return p(e)?new r(e,16).minus(new r("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new r(e,16)},h=function(t){var e=t.staticPart()||"0";return new r(e,16)},d=function(t){return m(t).dividedBy(new r(2).pow(128))},g=function(t){return h(t).dividedBy(new r(2).pow(128))},y=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t.staticPart()?!0:!1},v=function(t){return o.toAscii(t.staticPart())},b=function(t){return o.toAscii(t.dynamicPart().slice(64))},w=function(t){var e=t.staticPart();return"0x"+e.slice(e.length-40,e.length)};e.exports={formatInputInt:s,formatInputBytes:u,formatInputDynamicBytes:c,formatInputBool:l,formatInputReal:f,formatOutputInt:m,formatOutputUInt:h,formatOutputReal:d,formatOutputUReal:g,formatOutputBool:y,formatOutputBytes:v,formatOutputDynamicBytes:b,formatOutputAddress:w}},{"../utils/config":7,"../utils/utils":8,"./param":4,"bignumber.js":"bignumber.js"}],4:[function(t,e,n){var r=t("../utils/utils"),o=function(t,e){this.value=t||"",this.offset=e};o.prototype.dynamicPartLength=function(){return this.dynamicPart().length/2},o.prototype.withOffset=function(t){return new o(this.value,t)},o.prototype.combine=function(t){return new o(this.value+t.value)},o.prototype.isDynamic=function(){return this.value.length>64},o.prototype.offsetAsBytes=function(){return this.isDynamic()?r.padLeft(r.toTwosComplement(this.offset).toString(16),64):""},o.prototype.staticPart=function(){return this.isDynamic()?this.offsetAsBytes():this.value},o.prototype.dynamicPart=function(){return this.isDynamic()?this.value:""},o.prototype.encode=function(){return this.staticPart()+this.dynamicPart()},o.encodeList=function(t){var e=32*t.length,n=t.map(function(t){if(!t.isDynamic())return t;var n=e;return e+=t.dynamicPartLength(),t.withOffset(n)});return n.reduce(function(t,e){return t+e.dynamicPart()},n.reduce(function(t,e){return t+e.staticPart()},""))},o.decodeParam=function(t,e){return e=e||0,new o(t.substr(64*e,64))};var i=function(t,e){return parseInt("0x"+t.substr(64*e,64))};o.decodeBytes=function(t,e){e=e||0;var n=i(t,e);return new o(t.substr(2*n,128))},o.decodeArray=function(t,e){e=e||0;var n=i(t,e),r=parseInt("0x"+t.substr(2*n,64));return new o(t.substr(2*n,64*(r+1)))},e.exports=o},{"../utils/utils":8}],5:[function(t,e,n){var r=function(t,e){return t.filter(function(t){return"constructor"===t.type&&t.inputs.length===e})[0]};e.exports={getConstructor:r}},{}],6:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],7:[function(t,e,n){var r=t("bignumber.js"),o=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:o,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:r.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3,defaultBlock:"latest",defaultAccount:void 0}},{"bignumber.js":"bignumber.js"}],8:[function(t,e,n){var r=t("bignumber.js"),o={wei:"1",kwei:"1000",ada:"1000",mwei:"1000000",babbage:"1000000",gwei:"1000000000",shannon:"1000000000",szabo:"1000000000000",finney:"1000000000000000",ether:"1000000000000000000",kether:"1000000000000000000000",grand:"1000000000000000000000",einstein:"1000000000000000000000",mether:"1000000000000000000000000",gether:"1000000000000000000000000000",tether:"1000000000000000000000000000000"},i=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},a=function(t){var e="",n=0,r=t.length;for("0x"===t.substring(0,2)&&(n=2);r>n;n+=2){var o=parseInt(t.substr(n,2),16);if(0===o)break;e+=String.fromCharCode(o)}return e},s=function(t){for(var e="",n=0;nthis._inputTypes.length&&i.isObject(t[t.length-1])&&(e=t.pop()),e.to=this._address,e.data="0x"+this.signature()+o.encodeParams(this._inputTypes,t),e},a.prototype.signature=function(){return r.sha3(r.fromAscii(this._name)).slice(2,10)},a.prototype.call=function(){var t=this.toPayload.apply(this,Array.prototype.slice.call(arguments)),e=r.eth.call(t);e=e.length>=2?e.slice(2):e;var n=o.decodeParams(this._outputTypes,e);return 1===n.length?n[0]:n},a.prototype.sendTransaction=function(){var t=this.toPayload.apply(this,Array.prototype.slice.call(arguments));r.eth.sendTransaction(t)},a.prototype.displayName=function(){return i.extractDisplayName(this._name)},a.prototype.typeName=function(){return i.extractTypeName(this._name)},a.prototype.execute=function(){var t=!this._constant;return t?this.sendTransaction.apply(this,Array.prototype.slice.call(arguments)):this.call.apply(this,Array.prototype.slice.call(arguments))},a.prototype.attachToContract=function(t){var e=this.execute.bind(this);e.call=this.call.bind(this),e.sendTransaction=this.sendTransaction.bind(this);var n=this.displayName();t[n]||(t[n]=e),t[n][this.typeName()]=e},e.exports=a},{"../solidity/coder":2,"../utils/utils":8,"../web3":10}],19:[function(t,e,n){"use strict";var r=t("xmlhttprequest").XMLHttpRequest,o=t("./errors"),i=function(t){this.host=t||"http://localhost:8545"};i.prototype.send=function(t){var e=new r;e.open("POST",this.host,!1);try{e.send(JSON.stringify(t))}catch(n){throw o.InvalidConnection(this.host)}var i=e.responseText;try{i=JSON.parse(i)}catch(a){throw o.InvalidResponse(i)}return i},i.prototype.sendAsync=function(t,e){var n=new r;n.onreadystatechange=function(){if(4===n.readyState){var t=n.responseText,r=null;try{t=JSON.parse(t)}catch(i){r=o.InvalidResponse(t)}e(r,t)}},n.open("POST",this.host,!0);try{n.send(JSON.stringify(t))}catch(i){e(o.InvalidConnection(this.host))}},e.exports=i},{"./errors":13,xmlhttprequest:6}],20:[function(t,e,n){var r=function(){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,void(this.messageId=1))};r.getInstance=function(){var t=new r;return t},r.prototype.toPayload=function(t,e){return t||console.error("jsonrpc method should be specified!"),{jsonrpc:"2.0",method:t,params:e||[],id:this.messageId++}},r.prototype.isValidResponse=function(t){return!!t&&!t.error&&"2.0"===t.jsonrpc&&"number"==typeof t.id&&void 0!==t.result},r.prototype.toBatchPayload=function(t){var e=this;return t.map(function(t){return e.toPayload(t.method,t.params)})},e.exports=r},{}],21:[function(t,e,n){var r=t("./requestmanager"),o=t("../utils/utils"),i=t("./errors"),a=function(t){this.name=t.name,this.call=t.call,this.params=t.params||0,this.inputFormatter=t.inputFormatter,this.outputFormatter=t.outputFormatter};a.prototype.getCall=function(t){return o.isFunction(this.call)?this.call(t):this.call},a.prototype.extractCallback=function(t){return o.isFunction(t[t.length-1])?t.pop():null},a.prototype.validateArgs=function(t){if(t.length!==this.params)throw i.InvalidNumberOfParams()},a.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter.map(function(e,n){return e?e(t[n]):t[n]}):t},a.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},a.prototype.attachToObject=function(t){var e=this.send.bind(this);e.call=this.call;var n=this.name.split(".");n.length>1?(t[n[0]]=t[n[0]]||{},t[n[0]][n[1]]=e):t[n[0]]=e},a.prototype.toPayload=function(t){var e=this.getCall(t),n=this.extractCallback(t),r=this.formatInput(t);return this.validateArgs(r),{method:e,params:r,callback:n}},a.prototype.send=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));if(t.callback){var e=this;return r.getInstance().sendAsync(t,function(n,r){t.callback(null,e.formatOutput(r))})}return this.formatOutput(r.getInstance().send(t))},e.exports=a},{"../utils/utils":8,"./errors":13,"./requestmanager":25}],22:[function(t,e,n){var r=t("../utils/utils"),o=t("./property"),i=[],a=[new o({name:"listening",getter:"net_listening"}),new o({name:"peerCount",getter:"net_peerCount",outputFormatter:r.toDecimal})];e.exports={methods:i,properties:a}},{"../utils/utils":8,"./property":23}],23:[function(t,e,n){var r=t("./requestmanager"),o=function(t){this.name=t.name,this.getter=t.getter,this.setter=t.setter,this.outputFormatter=t.outputFormatter,this.inputFormatter=t.inputFormatter};o.prototype.formatInput=function(t){return this.inputFormatter?this.inputFormatter(t):t},o.prototype.formatOutput=function(t){return this.outputFormatter&&null!==t?this.outputFormatter(t):t},o.prototype.attachToObject=function(t){var e={get:this.get.bind(this),set:this.set.bind(this)},n=this.name.split(".");n.length>1?(t[n[0]]=t[n[0]]||{},Object.defineProperty(t[n[0]],n[1],e)):Object.defineProperty(t,n[0],e)},o.prototype.get=function(){return this.formatOutput(r.getInstance().send({method:this.getter}))},o.prototype.set=function(t){return r.getInstance().send({method:this.setter,params:[this.formatInput(t)]})},e.exports=o},{"./requestmanager":25}],24:[function(t,e,n){var r=function(){};r.prototype.send=function(t){var e=navigator.qt.callMethod(JSON.stringify(t));return JSON.parse(e)},e.exports=r},{}],25:[function(t,e,n){var r=t("./jsonrpc"),o=t("../utils/utils"),i=t("../utils/config"),a=t("./errors"),s=function(t){return arguments.callee._singletonInstance?arguments.callee._singletonInstance:(arguments.callee._singletonInstance=this,this.provider=t,this.polls=[],this.timeout=null,void this.poll())};s.getInstance=function(){var t=new s;return t},s.prototype.send=function(t){if(!this.provider)return console.error(a.InvalidProvider()),null;var e=r.getInstance().toPayload(t.method,t.params),n=this.provider.send(e);if(!r.getInstance().isValidResponse(n))throw a.InvalidResponse(n);return n.result},s.prototype.sendAsync=function(t,e){if(!this.provider)return e(a.InvalidProvider());var n=r.getInstance().toPayload(t.method,t.params);this.provider.sendAsync(n,function(t,n){return t?e(t):r.getInstance().isValidResponse(n)?void e(null,n.result):e(a.InvalidResponse(n))})},s.prototype.setProvider=function(t){this.provider=t},s.prototype.startPolling=function(t,e,n,r){this.polls.push({data:t,id:e,callback:n,uninstall:r})},s.prototype.stopPolling=function(t){for(var e=this.polls.length;e--;){var n=this.polls[e];n.id===t&&this.polls.splice(e,1)}},s.prototype.reset=function(){this.polls.forEach(function(t){t.uninstall(t.id)}),this.polls=[],this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.poll()},s.prototype.poll=function(){if(this.timeout=setTimeout(this.poll.bind(this),i.ETH_POLLING_TIMEOUT),this.polls.length){if(!this.provider)return void console.error(a.InvalidProvider());var t=r.getInstance().toBatchPayload(this.polls.map(function(t){return t.data})),e=this;this.provider.sendAsync(t,function(t,n){if(!t){if(!o.isArray(n))throw a.InvalidResponse(n);n.map(function(t,n){return t.callback=e.polls[n].callback,t}).filter(function(t){var e=r.getInstance().isValidResponse(t);return e||t.callback(a.InvalidResponse(t)),e}).filter(function(t){return o.isArray(t.result)&&t.result.length>0}).forEach(function(t){t.callback(null,t.result)})}})}},e.exports=s},{"../utils/config":7,"../utils/utils":8,"./errors":13,"./jsonrpc":20}],26:[function(t,e,n){var r=t("./method"),o=t("./formatters"),i=new r({name:"post",call:"shh_post",params:1,inputFormatter:[o.inputPostFormatter]}),a=new r({name:"newIdentity",call:"shh_newIdentity",params:0}),s=new r({name:"hasIdentity",call:"shh_hasIdentity",params:1}),u=new r({name:"newGroup",call:"shh_newGroup",params:0}),c=new r({name:"addToGroup",call:"shh_addToGroup",params:0}),l=[i,a,s,u,c];e.exports={methods:l}},{"./formatters":17,"./method":21}],27:[function(t,e,n){var r=t("./method"),o=function(){var t=function(t){return"string"==typeof t[0]?"eth_newBlockFilter":"eth_newFilter"},e=new r({name:"newFilter",call:t,params:1}),n=new r({name:"uninstallFilter",call:"eth_uninstallFilter",params:1}),o=new r({name:"getLogs",call:"eth_getFilterLogs",params:1}),i=new r({name:"poll",call:"eth_getFilterChanges",params:1});return[e,n,o,i]},i=function(){var t=new r({name:"newFilter",call:"shh_newFilter",params:1}),e=new r({name:"uninstallFilter",call:"shh_uninstallFilter",params:1}),n=new r({name:"getLogs",call:"shh_getMessages",params:1}),o=new r({name:"poll",call:"shh_getFilterChanges",params:1 +});return[t,e,n,o]};e.exports={eth:o,shh:i}},{"./method":21}],28:[function(t,e,n){},{}],"bignumber.js":[function(t,e,n){!function(n){"use strict";function r(t){function e(t,r){var o,i,a,s,u,c,l=this;if(!(l instanceof e))return J&&k(26,"constructor call without new",t),new e(t,r);if(null!=r&&V(r,2,64,R,"base")){if(r=0|r,c=t+"",10==r)return l=new e(t instanceof e?t:c),S(l,j+l.e+1,U);if((s="number"==typeof t)&&0*t!=0||!new RegExp("^-?"+(o="["+F.slice(0,r)+"]+")+"(?:\\."+o+")?$",37>r?"i":"").test(c))return d(l,c,s,r);s?(l.s=0>1/t?(c=c.slice(1),-1):1,J&&c.replace(/^0\.0*|\./,"").length>15&&k(R,_,t),s=!1):l.s=45===c.charCodeAt(0)?(c=c.slice(1),-1):1,c=n(c,10,r,l.s)}else{if(t instanceof e)return l.s=t.s,l.e=t.e,l.c=(t=t.c)?t.slice():t,void(R=0);if((s="number"==typeof t)&&0*t==0){if(l.s=0>1/t?(t=-t,-1):1,t===~~t){for(i=0,a=t;a>=10;a/=10,i++);return l.e=i,l.c=[t],void(R=0)}c=t+""}else{if(!g.test(c=t+""))return d(l,c,s);l.s=45===c.charCodeAt(0)?(c=c.slice(1),-1):1}}for((i=c.indexOf("."))>-1&&(c=c.replace(".","")),(a=c.search(/e/i))>0?(0>i&&(i=a),i+=+c.slice(a+1),c=c.substring(0,a)):0>i&&(i=c.length),a=0;48===c.charCodeAt(a);a++);for(u=c.length;48===c.charCodeAt(--u););if(c=c.slice(a,u+1))if(u=c.length,s&&J&&u>15&&k(R,_,l.s*t),i=i-a-1,i>G)l.c=l.e=null;else if(M>i)l.c=[l.e=0];else{if(l.e=i,l.c=[],a=(i+1)%I,0>i&&(a+=I),u>a){for(a&&l.c.push(+c.slice(0,a)),u-=I;u>a;)l.c.push(+c.slice(a,a+=I));c=c.slice(a),a=I-c.length}else a-=u;for(;a--;c+="0");l.c.push(+c)}else l.c=[l.e=0];R=0}function n(t,n,r,o){var a,s,u,l,p,m,h,d=t.indexOf("."),g=j,y=U;for(37>r&&(t=t.toLowerCase()),d>=0&&(u=z,z=0,t=t.replace(".",""),h=new e(r),p=h.pow(t.length-d),z=u,h.c=c(f(i(p.c),p.e),10,n),h.e=h.c.length),m=c(t,r,n),s=u=m.length;0==m[--u];m.pop());if(!m[0])return"0";if(0>d?--s:(p.c=m,p.e=s,p.s=o,p=E(p,h,g,y,n),m=p.c,l=p.r,s=p.e),a=s+g+1,d=m[a],u=n/2,l=l||0>a||null!=m[a+1],l=4>y?(null!=d||l)&&(0==y||y==(p.s<0?3:2)):d>u||d==u&&(4==y||l||6==y&&1&m[a-1]||y==(p.s<0?8:7)),1>a||!m[0])t=l?f("1",-g):"0";else{if(m.length=a,l)for(--n;++m[--a]>n;)m[a]=0,a||(++s,m.unshift(1));for(u=m.length;!m[--u];);for(d=0,t="";u>=d;t+=F.charAt(m[d++]));t=f(t,s)}return t}function m(t,n,r,o){var a,s,u,c,p;if(r=null!=r&&V(r,0,8,o,w)?0|r:U,!t.c)return t.toString();if(a=t.c[0],u=t.e,null==n)p=i(t.c),p=19==o||24==o&&H>=u?l(p,u):f(p,u);else if(t=S(new e(t),n,r),s=t.e,p=i(t.c),c=p.length,19==o||24==o&&(s>=n||H>=s)){for(;n>c;p+="0",c++);p=l(p,s)}else if(n-=u,p=f(p,s),s+1>c){if(--n>0)for(p+=".";n--;p+="0");}else if(n+=s-c,n>0)for(s+1==c&&(p+=".");n--;p+="0");return t.s<0&&a?"-"+p:p}function T(t,n){var r,o,i=0;for(u(t[0])&&(t=t[0]),r=new e(t[0]);++it||t>n||t!=p(t))&&k(r,(o||"decimal places")+(e>t||t>n?" out of range":" not an integer"),t),!0}function D(t,e,n){for(var r=1,o=e.length;!e[--o];e.pop());for(o=e[0];o>=10;o/=10,r++);return(n=r+n*I-1)>G?t.c=t.e=null:M>n?t.c=[t.e=0]:(t.e=n,t.c=e),t}function k(t,e,n){var r=new Error(["new BigNumber","cmp","config","div","divToInt","eq","gt","gte","lt","lte","minus","mod","plus","precision","random","round","shift","times","toDigits","toExponential","toFixed","toFormat","toFraction","pow","toPrecision","toString","BigNumber"][t]+"() "+e+": "+n);throw r.name="BigNumber Error",R=0,r}function S(t,e,n,r){var o,i,a,s,u,c,l,f=t.c,p=O;if(f){t:{for(o=1,s=f[0];s>=10;s/=10,o++);if(i=e-o,0>i)i+=I,a=e,u=f[c=0],l=u/p[o-a-1]%10|0;else if(c=y((i+1)/I),c>=f.length){if(!r)break t;for(;f.length<=c;f.push(0));u=l=0,o=1,i%=I,a=i-I+1}else{for(u=s=f[c],o=1;s>=10;s/=10,o++);i%=I,a=i-I+o,l=0>a?0:u/p[o-a-1]%10|0}if(r=r||0>e||null!=f[c+1]||(0>a?u:u%p[o-a-1]),r=4>n?(l||r)&&(0==n||n==(t.s<0?3:2)):l>5||5==l&&(4==n||r||6==n&&(i>0?a>0?u/p[o-a]:0:f[c-1])%10&1||n==(t.s<0?8:7)),1>e||!f[0])return f.length=0,r?(e-=t.e+1,f[0]=p[e%I],t.e=-e||0):f[0]=t.e=0,t;if(0==i?(f.length=c,s=1,c--):(f.length=c+1,s=p[I-i],f[c]=a>0?v(u/p[o-a]%p[a])*s:0),r)for(;;){if(0==c){for(i=1,a=f[0];a>=10;a/=10,i++);for(a=f[0]+=s,s=1;a>=10;a/=10,s++);i!=s&&(t.e++,f[0]==x&&(f[0]=1));break}if(f[c]+=s,f[c]!=x)break;f[c--]=0,s=1}for(i=f.length;0===f[--i];f.pop());}t.e>G?t.c=t.e=null:t.en?null!=(t=o[n++]):void 0};return a(e="DECIMAL_PLACES")&&V(t,0,P,2,e)&&(j=0|t),r[e]=j,a(e="ROUNDING_MODE")&&V(t,0,8,2,e)&&(U=0|t),r[e]=U,a(e="EXPONENTIAL_AT")&&(u(t)?V(t[0],-P,0,2,e)&&V(t[1],0,P,2,e)&&(H=0|t[0],q=0|t[1]):V(t,-P,P,2,e)&&(H=-(q=0|(0>t?-t:t)))),r[e]=[H,q],a(e="RANGE")&&(u(t)?V(t[0],-P,-1,2,e)&&V(t[1],1,P,2,e)&&(M=0|t[0],G=0|t[1]):V(t,-P,P,2,e)&&(0|t?M=-(G=0|(0>t?-t:t)):J&&k(2,e+" cannot be zero",t))),r[e]=[M,G],a(e="ERRORS")&&(t===!!t||1===t||0===t?(R=0,V=(J=!!t)?A:s):J&&k(2,e+b,t)),r[e]=J,a(e="CRYPTO")&&(t===!!t||1===t||0===t?(W=!(!t||!h||"object"!=typeof h),t&&!W&&J&&k(2,"crypto unavailable",h)):J&&k(2,e+b,t)),r[e]=W,a(e="MODULO_MODE")&&V(t,0,9,2,e)&&($=0|t),r[e]=$,a(e="POW_PRECISION")&&V(t,0,P,2,e)&&(z=0|t),r[e]=z,a(e="FORMAT")&&("object"==typeof t?X=t:J&&k(2,e+" not an object",t)),r[e]=X,r},e.max=function(){return T(arguments,C.lt)},e.min=function(){return T(arguments,C.gt)},e.random=function(){var t=9007199254740992,n=Math.random()*t&2097151?function(){return v(Math.random()*t)}:function(){return 8388608*(1073741824*Math.random()|0)+(8388608*Math.random()|0)};return function(t){var r,o,i,a,s,u=0,c=[],l=new e(L);if(t=null!=t&&V(t,0,P,14)?0|t:j,a=y(t/I),W)if(h&&h.getRandomValues){for(r=h.getRandomValues(new Uint32Array(a*=2));a>u;)s=131072*r[u]+(r[u+1]>>>11),s>=9e15?(o=h.getRandomValues(new Uint32Array(2)),r[u]=o[0],r[u+1]=o[1]):(c.push(s%1e14),u+=2);u=a/2}else if(h&&h.randomBytes){for(r=h.randomBytes(a*=7);a>u;)s=281474976710656*(31&r[u])+1099511627776*r[u+1]+4294967296*r[u+2]+16777216*r[u+3]+(r[u+4]<<16)+(r[u+5]<<8)+r[u+6],s>=9e15?h.randomBytes(7).copy(r,u):(c.push(s%1e14),u+=7);u=a/7}else J&&k(14,"crypto unavailable",h);if(!u)for(;a>u;)s=n(),9e15>s&&(c[u++]=s%1e14);for(a=c[--u],t%=I,a&&t&&(s=O[I-t],c[u]=v(a/s)*s);0===c[u];c.pop(),u--);if(0>u)c=[i=0];else{for(i=-1;0===c[0];c.shift(),i-=I);for(u=1,s=c[0];s>=10;s/=10,u++);I>u&&(i-=I-u)}return l.e=i,l.c=c,l}}(),E=function(){function t(t,e,n){var r,o,i,a,s=0,u=t.length,c=e%B,l=e/B|0;for(t=t.slice();u--;)i=t[u]%B,a=t[u]/B|0,r=l*i+a*c,o=c*i+r%B*B+s,s=(o/n|0)+(r/B|0)+l*a,t[u]=o%n;return s&&t.unshift(s),t}function n(t,e,n,r){var o,i;if(n!=r)i=n>r?1:-1;else for(o=i=0;n>o;o++)if(t[o]!=e[o]){i=t[o]>e[o]?1:-1;break}return i}function r(t,e,n,r){for(var o=0;n--;)t[n]-=o,o=t[n]1;t.shift());}return function(i,a,s,u,c){var l,f,p,m,h,d,g,y,b,w,_,F,N,O,B,P,T,A=i.s==a.s?1:-1,D=i.c,k=a.c;if(!(D&&D[0]&&k&&k[0]))return new e(i.s&&a.s&&(D?!k||D[0]!=k[0]:k)?D&&0==D[0]||!k?0*A:A/0:0/0);for(y=new e(A),b=y.c=[],f=i.e-a.e,A=s+f+1,c||(c=x,f=o(i.e/I)-o(a.e/I),A=A/I|0),p=0;k[p]==(D[p]||0);p++);if(k[p]>(D[p]||0)&&f--,0>A)b.push(1),m=!0;else{for(O=D.length,P=k.length,p=0,A+=2,h=v(c/(k[0]+1)),h>1&&(k=t(k,h,c),D=t(D,h,c),P=k.length,O=D.length),N=P,w=D.slice(0,P),_=w.length;P>_;w[_++]=0);T=k.slice(),T.unshift(0),B=k[0],k[1]>=c/2&&B++;do{if(h=0,l=n(k,w,P,_),0>l){if(F=w[0],P!=_&&(F=F*c+(w[1]||0)),h=v(F/B),h>1)for(h>=c&&(h=c-1),d=t(k,h,c),g=d.length,_=w.length;1==n(d,w,g,_);)h--,r(d,g>P?T:k,g,c),g=d.length,l=1;else 0==h&&(l=h=1),d=k.slice(),g=d.length;if(_>g&&d.unshift(0),r(w,d,_,c),_=w.length,-1==l)for(;n(k,w,P,_)<1;)h++,r(w,_>P?T:k,_,c),_=w.length}else 0===l&&(h++,w=[0]);b[p++]=h,w[0]?w[_++]=D[N]||0:(w=[D[N]],_=1)}while((N++=10;A/=10,p++);S(y,s+(y.e=p+f*I-1)+1,u,m)}else y.e=f,y.r=+m;return y}}(),d=function(){var t=/^(-?)0([xbo])/i,n=/^([^.]+)\.$/,r=/^\.([^.]+)$/,o=/^-?(Infinity|NaN)$/,i=/^\s*\+|^\s+|\s+$/g;return function(a,s,u,c){var l,f=u?s:s.replace(i,"");if(o.test(f))a.s=isNaN(f)?null:0>f?-1:1;else{if(!u&&(f=f.replace(t,function(t,e,n){return l="x"==(n=n.toLowerCase())?16:"b"==n?2:8,c&&c!=l?t:e}),c&&(l=c,f=f.replace(n,"$1").replace(r,"0.$1")),s!=f))return new e(f,l);J&&k(R,"not a"+(c?" base "+c:"")+" number",s),a.s=null}a.c=a.e=null,R=0}}(),C.absoluteValue=C.abs=function(){var t=new e(this);return t.s<0&&(t.s=1),t},C.ceil=function(){return S(new e(this),this.e+1,2)},C.comparedTo=C.cmp=function(t,n){return R=1,a(this,new e(t,n))},C.decimalPlaces=C.dp=function(){var t,e,n=this.c;if(!n)return null;if(t=((e=n.length-1)-o(this.e/I))*I,e=n[e])for(;e%10==0;e/=10,t--);return 0>t&&(t=0),t},C.dividedBy=C.div=function(t,n){return R=3,E(this,new e(t,n),j,U)},C.dividedToIntegerBy=C.divToInt=function(t,n){return R=4,E(this,new e(t,n),0,1)},C.equals=C.eq=function(t,n){return R=5,0===a(this,new e(t,n))},C.floor=function(){return S(new e(this),this.e+1,3)},C.greaterThan=C.gt=function(t,n){return R=6,a(this,new e(t,n))>0},C.greaterThanOrEqualTo=C.gte=function(t,n){return R=7,1===(n=a(this,new e(t,n)))||0===n},C.isFinite=function(){return!!this.c},C.isInteger=C.isInt=function(){return!!this.c&&o(this.e/I)>this.c.length-2},C.isNaN=function(){return!this.s},C.isNegative=C.isNeg=function(){return this.s<0},C.isZero=function(){return!!this.c&&0==this.c[0]},C.lessThan=C.lt=function(t,n){return R=8,a(this,new e(t,n))<0},C.lessThanOrEqualTo=C.lte=function(t,n){return R=9,-1===(n=a(this,new e(t,n)))||0===n},C.minus=C.sub=function(t,n){var r,i,a,s,u=this,c=u.s;if(R=10,t=new e(t,n),n=t.s,!c||!n)return new e(0/0);if(c!=n)return t.s=-n,u.plus(t);var l=u.e/I,f=t.e/I,p=u.c,m=t.c;if(!l||!f){if(!p||!m)return p?(t.s=-n,t):new e(m?u:0/0);if(!p[0]||!m[0])return m[0]?(t.s=-n,t):new e(p[0]?u:3==U?-0:0)}if(l=o(l),f=o(f),p=p.slice(),c=l-f){for((s=0>c)?(c=-c,a=p):(f=l,a=m),a.reverse(),n=c;n--;a.push(0));a.reverse()}else for(i=(s=(c=p.length)<(n=m.length))?c:n,c=n=0;i>n;n++)if(p[n]!=m[n]){s=p[n]0)for(;n--;p[r++]=0);for(n=x-1;i>c;){if(p[--i]0?(u=s,r=l):(a=-a,r=c),r.reverse();a--;r.push(0));r.reverse()}for(a=c.length,n=l.length,0>a-n&&(r=l,l=c,c=r,n=a),a=0;n;)a=(c[--n]=c[n]+l[n]+a)/x|0,c[n]%=x;return a&&(c.unshift(a),++u),D(t,c,u)},C.precision=C.sd=function(t){var e,n,r=this,o=r.c;if(null!=t&&t!==!!t&&1!==t&&0!==t&&(J&&k(13,"argument"+b,t),t!=!!t&&(t=null)),!o)return null;if(n=o.length-1,e=n*I+1,n=o[n]){for(;n%10==0;n/=10,e--);for(n=o[0];n>=10;n/=10,e++);}return t&&r.e+1>e&&(e=r.e+1),e},C.round=function(t,n){var r=new e(this);return(null==t||V(t,0,P,15))&&S(r,~~t+this.e+1,null!=n&&V(n,0,8,15,w)?0|n:U),r},C.shift=function(t){var n=this;return V(t,-N,N,16,"argument")?n.times("1e"+p(t)):new e(n.c&&n.c[0]&&(-N>t||t>N)?n.s*(0>t?0:1/0):n)},C.squareRoot=C.sqrt=function(){var t,n,r,a,s,u=this,c=u.c,l=u.s,f=u.e,p=j+4,m=new e("0.5");if(1!==l||!c||!c[0])return new e(!l||0>l&&(!c||c[0])?0/0:c?u:1/0);if(l=Math.sqrt(+u),0==l||l==1/0?(n=i(c),(n.length+f)%2==0&&(n+="0"),l=Math.sqrt(n),f=o((f+1)/2)-(0>f||f%2),l==1/0?n="1e"+f:(n=l.toExponential(),n=n.slice(0,n.indexOf("e")+1)+f),r=new e(n)):r=new e(l+""),r.c[0])for(f=r.e,l=f+p,3>l&&(l=0);;)if(s=r,r=m.times(s.plus(E(u,s,p,1))),i(s.c).slice(0,l)===(n=i(r.c)).slice(0,l)){if(r.el&&(g=w,w=_,_=g,a=l,l=m,m=a),a=l+m,g=[];a--;g.push(0));for(y=x,v=B,a=m;--a>=0;){for(r=0,h=_[a]%v,d=_[a]/v|0,u=l,s=a+u;s>a;)f=w[--u]%v,p=w[u]/v|0,c=d*f+p*h,f=h*f+c%v*v+g[s]+r,r=(f/y|0)+(c/v|0)+d*p,g[s--]=f%y;g[s]=r}return r?++i:g.shift(),D(t,g,i)},C.toDigits=function(t,n){var r=new e(this);return t=null!=t&&V(t,1,P,18,"precision")?0|t:null,n=null!=n&&V(n,0,8,18,w)?0|n:U,t?S(r,t,n):r},C.toExponential=function(t,e){return m(this,null!=t&&V(t,0,P,19)?~~t+1:null,e,19)},C.toFixed=function(t,e){return m(this,null!=t&&V(t,0,P,20)?~~t+this.e+1:null,e,20)},C.toFormat=function(t,e){var n=m(this,null!=t&&V(t,0,P,21)?~~t+this.e+1:null,e,21);if(this.c){var r,o=n.split("."),i=+X.groupSize,a=+X.secondaryGroupSize,s=X.groupSeparator,u=o[0],c=o[1],l=this.s<0,f=l?u.slice(1):u,p=f.length;if(a&&(r=i,i=a,a=r,p-=r),i>0&&p>0){for(r=p%i||i,u=f.substr(0,r);p>r;r+=i)u+=s+f.substr(r,i);a>0&&(u+=s+f.slice(r)),l&&(u="-"+u)}n=c?u+X.decimalSeparator+((a=+X.fractionGroupSize)?c.replace(new RegExp("\\d{"+a+"}\\B","g"),"$&"+X.fractionGroupSeparator):c):u}return n},C.toFraction=function(t){var n,r,o,a,s,u,c,l,f,p=J,m=this,h=m.c,d=new e(L),g=r=new e(L),y=c=new e(L);if(null!=t&&(J=!1,u=new e(t),J=p,(!(p=u.isInt())||u.lt(L))&&(J&&k(22,"max denominator "+(p?"out of range":"not an integer"),t),t=!p&&u.c&&S(u,u.e+1,1).gte(L)?u:null)),!h)return m.toString();for(f=i(h),a=d.e=f.length-m.e-1,d.c[0]=O[(s=a%I)<0?I+s:s],t=!t||u.cmp(d)>0?a>0?d:g:u,s=G,G=1/0,u=new e(f),c.c[0]=0;l=E(u,d,0,1),o=r.plus(l.times(y)),1!=o.cmp(t);)r=y,y=o,g=c.plus(l.times(o=g)),c=o,d=u.minus(l.times(o=d)),u=o;return o=E(t.minus(r),y,0,1),c=c.plus(o.times(g)),r=r.plus(o.times(y)),c.s=g.s=m.s,a*=2,n=E(g,y,a,U).minus(m).abs().cmp(E(c,r,a,U).minus(m).abs())<1?[g.toString(),y.toString()]:[c.toString(),r.toString()],G=s,n},C.toNumber=function(){var t=this;return+t||(t.s?0*t.s:0/0)},C.toPower=C.pow=function(t){var n,r,o=v(0>t?-t:+t),i=this;if(!V(t,-N,N,23,"exponent")&&(!isFinite(t)||o>N&&(t/=0)||parseFloat(t)!=t&&!(t=0/0)))return new e(Math.pow(+i,t));for(n=z?y(z/I+2):0,r=new e(L);;){if(o%2){if(r=r.times(i),!r.c)break;n&&r.c.length>n&&(r.c.length=n)}if(o=v(o/2),!o)break;i=i.times(i),n&&i.c&&i.c.length>n&&(i.c.length=n)}return 0>t&&(r=L.div(r)),n?S(r,z,U):r},C.toPrecision=function(t,e){return m(this,null!=t&&V(t,1,P,24,"precision")?0|t:null,e,24)},C.toString=function(t){var e,r=this,o=r.s,a=r.e;return null===a?o?(e="Infinity",0>o&&(e="-"+e)):e="NaN":(e=i(r.c),e=null!=t&&V(t,2,64,25,"base")?n(f(e,a),0|t,10,o):H>=a||a>=q?l(e,a):f(e,a),0>o&&r.c[0]&&(e="-"+e)),e},C.truncated=C.trunc=function(){return S(new e(this),this.e+1,1)},C.valueOf=C.toJSON=function(){return this.toString()},null!=t&&e.config(t),e}function o(t){var e=0|t;return t>0||t===e?e:e-1}function i(t){for(var e,n,r=1,o=t.length,i=t[0]+"";o>r;){for(e=t[r++]+"",n=I-e.length;n--;e="0"+e);i+=e}for(o=i.length;48===i.charCodeAt(--o););return i.slice(0,o+1||1)}function a(t,e){var n,r,o=t.c,i=e.c,a=t.s,s=e.s,u=t.e,c=e.e;if(!a||!s)return null;if(n=o&&!o[0],r=i&&!i[0],n||r)return n?r?0:-s:a;if(a!=s)return a;if(n=0>a,r=u==c,!o||!i)return r?0:!o^n?1:-1;if(!r)return u>c^n?1:-1;for(s=(u=o.length)<(c=i.length)?u:c,a=0;s>a;a++)if(o[a]!=i[a])return o[a]>i[a]^n?1:-1;return u==c?0:u>c^n?1:-1}function s(t,e,n){return(t=p(t))>=e&&n>=t}function u(t){return"[object Array]"==Object.prototype.toString.call(t)}function c(t,e,n){for(var r,o,i=[0],a=0,s=t.length;s>a;){for(o=i.length;o--;i[o]*=e);for(i[r=0]+=F.indexOf(t.charAt(a++));rn-1&&(null==i[r+1]&&(i[r+1]=0),i[r+1]+=i[r]/n|0,i[r]%=n)}return i.reverse()}function l(t,e){return(t.length>1?t.charAt(0)+"."+t.slice(1):t)+(0>e?"e":"e+")+e}function f(t,e){var n,r;if(0>e){for(r="0.";++e;r+="0");t=r+t}else if(n=t.length,++e>n){for(r="0",e-=n;--e;r+="0");t+=r}else n>e&&(t=t.slice(0,e)+"."+t.slice(e));return t}function p(t){return t=parseFloat(t),0>t?y(t):v(t)}var m,h,d,g=/^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,y=Math.ceil,v=Math.floor,b=" not a boolean or binary digit",w="rounding mode",_="number type has more than 15 significant digits",F="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_",x=1e14,I=14,N=9007199254740991,O=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],B=1e7,P=1e9;if(m=r(),"function"==typeof define&&define.amd)define(function(){return m});else if("undefined"!=typeof e&&e.exports){if(e.exports=m,!h)try{h=t("crypto")}catch(T){}}else n.BigNumber=m}(this)},{crypto:28}],web3:[function(t,e,n){var r=t("./lib/web3");r.providers.HttpProvider=t("./lib/web3/httpprovider"),r.providers.QtSyncProvider=t("./lib/web3/qtsync"),r.eth.contract=t("./lib/web3/contract"),r.abi=t("./lib/solidity/abi"),"undefined"!=typeof window&&"undefined"==typeof window.web3&&(window.web3=r),e.exports=r},{"./lib/solidity/abi":1,"./lib/web3":10,"./lib/web3/contract":11,"./lib/web3/httpprovider":19,"./lib/web3/qtsync":24}]},{},["web3"]); \ No newline at end of file diff --git a/libjsqrc/ethereumjs/example/event_inc.html b/libjsqrc/ethereumjs/example/event_inc.html index 74bcb9c4b..ac12c6447 100644 --- a/libjsqrc/ethereumjs/example/event_inc.html +++ b/libjsqrc/ethereumjs/example/event_inc.html @@ -45,7 +45,7 @@ var contract; var update = function (err, x) { - document.getElementById('result').innerText = JSON.stringify(x, null, 2); + document.getElementById('result').textContent = JSON.stringify(x, null, 2); }; var createContract = function () { diff --git a/libjsqrc/ethereumjs/lib/solidity/abi.js b/libjsqrc/ethereumjs/lib/solidity/abi.js index e9299c386..feb139ed4 100644 --- a/libjsqrc/ethereumjs/lib/solidity/abi.js +++ b/libjsqrc/ethereumjs/lib/solidity/abi.js @@ -21,113 +21,24 @@ * @date 2014 */ -var utils = require('../utils/utils'); var coder = require('./coder'); -var solUtils = require('./utils'); - -/** - * Formats input params to bytes - * - * @method formatInput - * @param {Array} abi inputs of method - * @param {Array} params that will be formatted to bytes - * @returns bytes representation of input params - */ -var formatInput = function (inputs, params) { - var i = inputs.map(function (input) { - return input.type; - }); - return coder.encodeParams(i, params); -}; - -/** - * Formats output bytes back to param list - * - * @method formatOutput - * @param {Array} abi outputs of method - * @param {String} bytes represention of output - * @returns {Array} output params - */ -var formatOutput = function (outs, bytes) { - var o = outs.map(function (out) { - return out.type; - }); - - return coder.decodeParams(o, bytes); -}; - -/** - * Should be called to create input parser for contract with given abi - * - * @method inputParser - * @param {Array} contract abi - * @returns {Object} input parser object for given json abi - * TODO: refactor creating the parser, do not double logic from contract - */ -var inputParser = function (json) { - var parser = {}; - json.forEach(function (method) { - var displayName = utils.extractDisplayName(method.name); - var typeName = utils.extractTypeName(method.name); - - var impl = function () { - var params = Array.prototype.slice.call(arguments); - return formatInput(method.inputs, params); - }; - - if (parser[displayName] === undefined) { - parser[displayName] = impl; - } - - parser[displayName][typeName] = impl; - }); - - return parser; -}; - -/** - * Should be called to create output parser for contract with given abi - * - * @method outputParser - * @param {Array} contract abi - * @returns {Object} output parser for given json abi - */ -var outputParser = function (json) { - var parser = {}; - json.forEach(function (method) { - - var displayName = utils.extractDisplayName(method.name); - var typeName = utils.extractTypeName(method.name); - - var impl = function (output) { - return formatOutput(method.outputs, output); - }; - - if (parser[displayName] === undefined) { - parser[displayName] = impl; - } - - parser[displayName][typeName] = impl; - }); - - return parser; -}; +var utils = require('./utils'); var formatConstructorParams = function (abi, params) { - var constructor = solUtils.getConstructor(abi, params.length); + var constructor = utils.getConstructor(abi, params.length); if (!constructor) { if (params.length > 0) { console.warn("didn't found matching constructor, using default one"); } return ''; } - return formatInput(constructor.inputs, params); + + return coder.encodeParams(constructor.inputs.map(function (input) { + return input.type; + }), params); }; module.exports = { - inputParser: inputParser, - outputParser: outputParser, - formatInput: formatInput, - formatOutput: formatOutput, formatConstructorParams: formatConstructorParams }; + diff --git a/libjsqrc/ethereumjs/lib/solidity/coder.js b/libjsqrc/ethereumjs/lib/solidity/coder.js index 76de8d426..b46a38b0b 100644 --- a/libjsqrc/ethereumjs/lib/solidity/coder.js +++ b/libjsqrc/ethereumjs/lib/solidity/coder.js @@ -77,9 +77,8 @@ SolidityType.prototype.formatInput = function (param, arrayType) { return param.map(function (p) { return self._inputFormatter(p); }).reduce(function (acc, current) { - acc.appendArrayElement(current); - return acc; - }, new SolidityParam('', f.formatInputInt(param.length).value)); + return acc.combine(current); + }, f.formatInputInt(param.length)).withOffset(32); } return this._inputFormatter(param); }; @@ -96,9 +95,9 @@ SolidityType.prototype.formatOutput = function (param, arrayType) { if (arrayType) { // let's assume, that we solidity will never return long arrays :P var result = []; - var length = new BigNumber(param.prefix, 16); + var length = new BigNumber(param.dynamicPart().slice(0, 64), 16); for (var i = 0; i < length * 64; i += 64) { - result.push(this._outputFormatter(new SolidityParam(param.suffix.slice(i, i + 64)))); + result.push(this._outputFormatter(new SolidityParam(param.dynamicPart().substr(i + 64, 64)))); } return result; } @@ -106,31 +105,21 @@ SolidityType.prototype.formatOutput = function (param, arrayType) { }; /** - * Should be used to check if a type is variadic + * Should be used to slice single param from bytes * - * @method isVariadicType - * @param {String} type - * @returns {Bool} true if the type is variadic - */ -SolidityType.prototype.isVariadicType = function (type) { - return isArrayType(type) || this._mode === 'bytes'; -}; - -/** - * Should be used to shift param from params group - * - * @method shiftParam + * @method sliceParam + * @param {String} bytes + * @param {Number} index of param to slice * @param {String} type - * @returns {SolidityParam} shifted param + * @returns {SolidityParam} param */ -SolidityType.prototype.shiftParam = function (type, param) { +SolidityType.prototype.sliceParam = function (bytes, index, type) { if (this._mode === 'bytes') { - return param.shiftBytes(); + return SolidityParam.decodeBytes(bytes, index); } else if (isArrayType(type)) { - var length = new BigNumber(param.prefix.slice(0, 64), 16); - return param.shiftArray(length); + return SolidityParam.decodeArray(bytes, index); } - return param.shiftValue(); + return SolidityParam.decodeParam(bytes, index); }; /** @@ -160,28 +149,6 @@ SolidityCoder.prototype._requireType = function (type) { return solidityType; }; -/** - * Should be used to transform plain bytes to SolidityParam object - * - * @method _bytesToParam - * @param {Array} types of params - * @param {String} bytes to be transformed to SolidityParam - * @return {SolidityParam} SolidityParam for this group of params - */ -SolidityCoder.prototype._bytesToParam = function (types, bytes) { - var self = this; - var prefixTypes = types.reduce(function (acc, type) { - return self._requireType(type).isVariadicType(type) ? acc + 1 : acc; - }, 0); - var valueTypes = types.length - prefixTypes; - - var prefix = bytes.slice(0, prefixTypes * 64); - bytes = bytes.slice(prefixTypes * 64); - var value = bytes.slice(0, valueTypes * 64); - var suffix = bytes.slice(valueTypes * 64); - return new SolidityParam(value, prefix, suffix); -}; - /** * Should be used to transform plain param of given type to SolidityParam * @@ -216,24 +183,11 @@ SolidityCoder.prototype.encodeParam = function (type, param) { */ SolidityCoder.prototype.encodeParams = function (types, params) { var self = this; - return types.map(function (type, index) { + var solidityParams = types.map(function (type, index) { return self._formatInput(type, params[index]); - }).reduce(function (acc, solidityParam) { - acc.append(solidityParam); - return acc; - }, new SolidityParam()).encode(); -}; + }); -/** - * Should be used to transform SolidityParam to plain param - * - * @method _formatOutput - * @param {String} type - * @param {SolidityParam} param - * @return {Object} plain param - */ -SolidityCoder.prototype._formatOutput = function (type, param) { - return this._requireType(type).formatOutput(param, isArrayType(type)); + return SolidityParam.encodeList(solidityParams); }; /** @@ -245,7 +199,7 @@ SolidityCoder.prototype._formatOutput = function (type, param) { * @return {Object} plain param */ SolidityCoder.prototype.decodeParam = function (type, bytes) { - return this._formatOutput(type, this._bytesToParam([type], bytes)); + return this.decodeParams([type], bytes)[0]; }; /** @@ -258,10 +212,9 @@ SolidityCoder.prototype.decodeParam = function (type, bytes) { */ SolidityCoder.prototype.decodeParams = function (types, bytes) { var self = this; - var param = this._bytesToParam(types, bytes); - return types.map(function (type) { + return types.map(function (type, index) { var solidityType = self._requireType(type); - var p = solidityType.shiftParam(type, param); + var p = solidityType.sliceParam(bytes, index, type); return solidityType.formatOutput(p, isArrayType(type)); }); }; diff --git a/libjsqrc/ethereumjs/lib/solidity/formatters.js b/libjsqrc/ethereumjs/lib/solidity/formatters.js index a4ff3406c..3db936528 100644 --- a/libjsqrc/ethereumjs/lib/solidity/formatters.js +++ b/libjsqrc/ethereumjs/lib/solidity/formatters.js @@ -63,7 +63,7 @@ var formatInputBytes = function (value) { */ var formatInputDynamicBytes = function (value) { var result = utils.fromAscii(value, c.ETH_PADDING).substr(2); - return new SolidityParam('', formatInputInt(value.length).value, result); + return new SolidityParam(formatInputInt(value.length).value + result, 32); }; /** @@ -109,7 +109,7 @@ var signedIsNegative = function (value) { * @returns {BigNumber} right-aligned output bytes formatted to big number */ var formatOutputInt = function (param) { - var value = param.value || "0"; + var value = param.staticPart() || "0"; // check if it's negative number // it it is, return two's complement @@ -127,7 +127,7 @@ var formatOutputInt = function (param) { * @returns {BigNumeber} right-aligned output bytes formatted to uint */ var formatOutputUInt = function (param) { - var value = param.value || "0"; + var value = param.staticPart() || "0"; return new BigNumber(value, 16); }; @@ -161,7 +161,7 @@ var formatOutputUReal = function (param) { * @returns {Boolean} right-aligned input bytes formatted to bool */ var formatOutputBool = function (param) { - return param.value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false; + return param.staticPart() === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false; }; /** @@ -173,7 +173,7 @@ var formatOutputBool = function (param) { */ var formatOutputBytes = function (param) { // length might also be important! - return utils.toAscii(param.value); + return utils.toAscii(param.staticPart()); }; /** @@ -185,7 +185,7 @@ var formatOutputBytes = function (param) { */ var formatOutputDynamicBytes = function (param) { // length might also be important! - return utils.toAscii(param.suffix); + return utils.toAscii(param.dynamicPart().slice(64)); }; /** @@ -196,7 +196,7 @@ var formatOutputDynamicBytes = function (param) { * @returns {String} address */ var formatOutputAddress = function (param) { - var value = param.value; + var value = param.staticPart(); return "0x" + value.slice(value.length - 40, value.length); }; diff --git a/libjsqrc/ethereumjs/lib/solidity/param.js b/libjsqrc/ethereumjs/lib/solidity/param.js index 15ba0c61f..7c3254659 100644 --- a/libjsqrc/ethereumjs/lib/solidity/param.js +++ b/libjsqrc/ethereumjs/lib/solidity/param.js @@ -20,85 +20,190 @@ * @date 2015 */ +var utils = require('../utils/utils'); + /** * SolidityParam object prototype. * Should be used when encoding, decoding solidity bytes */ -var SolidityParam = function (value, prefix, suffix) { - this.prefix = prefix || ''; +var SolidityParam = function (value, offset) { this.value = value || ''; - this.suffix = suffix || ''; + this.offset = offset; // offset in bytes +}; + +/** + * This method should be used to get length of params's dynamic part + * + * @method dynamicPartLength + * @returns {Number} length of dynamic part (in bytes) + */ +SolidityParam.prototype.dynamicPartLength = function () { + return this.dynamicPart().length / 2; +}; + +/** + * This method should be used to create copy of solidity param with different offset + * + * @method withOffset + * @param {Number} offset length in bytes + * @returns {SolidityParam} new solidity param with applied offset + */ +SolidityParam.prototype.withOffset = function (offset) { + return new SolidityParam(this.value, offset); +}; + +/** + * This method should be used to combine solidity params together + * eg. when appending an array + * + * @method combine + * @param {SolidityParam} param with which we should combine + * @param {SolidityParam} result of combination + */ +SolidityParam.prototype.combine = function (param) { + return new SolidityParam(this.value + param.value); +}; + +/** + * This method should be called to check if param has dynamic size. + * If it has, it returns true, otherwise false + * + * @method isDynamic + * @returns {Boolean} + */ +SolidityParam.prototype.isDynamic = function () { + return this.value.length > 64; }; /** - * This method should be used to encode two params one after another + * This method should be called to transform offset to bytes * - * @method append - * @param {SolidityParam} param that it appended after this + * @method offsetAsBytes + * @returns {String} bytes representation of offset */ -SolidityParam.prototype.append = function (param) { - this.prefix += param.prefix; - this.value += param.value; - this.suffix += param.suffix; +SolidityParam.prototype.offsetAsBytes = function () { + return !this.isDynamic() ? '' : utils.padLeft(utils.toTwosComplement(this.offset).toString(16), 64); }; /** - * This method should be used to encode next param in an array + * This method should be called to get static part of param * - * @method appendArrayElement - * @param {SolidityParam} param that is appended to an array + * @method staticPart + * @returns {String} offset if it is a dynamic param, otherwise value */ -SolidityParam.prototype.appendArrayElement = function (param) { - this.suffix += param.value; - this.prefix += param.prefix; - // TODO: suffix not supported = it's required for nested arrays; +SolidityParam.prototype.staticPart = function () { + if (!this.isDynamic()) { + return this.value; + } + return this.offsetAsBytes(); }; /** - * This method should be used to create bytearrays from param + * This method should be called to get dynamic part of param + * + * @method dynamicPart + * @returns {String} returns a value if it is a dynamic param, otherwise empty string + */ +SolidityParam.prototype.dynamicPart = function () { + return this.isDynamic() ? this.value : ''; +}; + +/** + * This method should be called to encode param * * @method encode - * @return {String} encoded param(s) + * @returns {String} */ SolidityParam.prototype.encode = function () { - return this.prefix + this.value + this.suffix; + return this.staticPart() + this.dynamicPart(); }; /** - * This method should be used to shift first param from group of params + * This method should be called to encode array of params * - * @method shiftValue - * @return {SolidityParam} first value param + * @method encodeList + * @param {Array[SolidityParam]} params + * @returns {String} */ -SolidityParam.prototype.shiftValue = function () { - var value = this.value.slice(0, 64); - this.value = this.value.slice(64); - return new SolidityParam(value); +SolidityParam.encodeList = function (params) { + + // updating offsets + var totalOffset = params.length * 32; + var offsetParams = params.map(function (param) { + if (!param.isDynamic()) { + return param; + } + var offset = totalOffset; + totalOffset += param.dynamicPartLength(); + return param.withOffset(offset); + }); + + // encode everything! + return offsetParams.reduce(function (result, param) { + return result + param.dynamicPart(); + }, offsetParams.reduce(function (result, param) { + return result + param.staticPart(); + }, '')); }; /** - * This method should be used to first bytes param from group of params + * This method should be used to decode plain (static) solidity param at given index * - * @method shiftBytes - * @return {SolidityParam} first bytes param + * @method decodeParam + * @param {String} bytes + * @param {Number} index + * @returns {SolidityParam} */ -SolidityParam.prototype.shiftBytes = function () { - return this.shiftArray(1); +SolidityParam.decodeParam = function (bytes, index) { + index = index || 0; + return new SolidityParam(bytes.substr(index * 64, 64)); }; /** - * This method should be used to shift an array from group of params - * - * @method shiftArray - * @param {Number} size of an array to shift - * @return {SolidityParam} first array param + * This method should be called to get offset value from bytes at given index + * + * @method getOffset + * @param {String} bytes + * @param {Number} index + * @returns {Number} offset as number + */ +var getOffset = function (bytes, index) { + // we can do this cause offset is rather small + return parseInt('0x' + bytes.substr(index * 64, 64)); +}; + +/** + * This method should be called to decode solidity bytes param at given index + * + * @method decodeBytes + * @param {String} bytes + * @param {Number} index + * @returns {SolidityParam} + */ +SolidityParam.decodeBytes = function (bytes, index) { + index = index || 0; + //TODO add support for strings longer than 32 bytes + //var length = parseInt('0x' + bytes.substr(offset * 64, 64)); + + var offset = getOffset(bytes, index); + + // 2 * , cause we also parse length + return new SolidityParam(bytes.substr(offset * 2, 2 * 64)); +}; + +/** + * This method should be used to decode solidity array at given index + * + * @method decodeArray + * @param {String} bytes + * @param {Number} index + * @returns {SolidityParam} */ -SolidityParam.prototype.shiftArray = function (length) { - var prefix = this.prefix.slice(0, 64); - this.prefix = this.value.slice(64); - var suffix = this.suffix.slice(0, 64 * length); - this.suffix = this.suffix.slice(64 * length); - return new SolidityParam('', prefix, suffix); +SolidityParam.decodeArray = function (bytes, index) { + index = index || 0; + var offset = getOffset(bytes, index); + var length = parseInt('0x' + bytes.substr(offset * 2, 64)); + return new SolidityParam(bytes.substr(offset * 2, (length + 1) * 64)); }; module.exports = SolidityParam; diff --git a/libjsqrc/ethereumjs/lib/solidity/utils.js b/libjsqrc/ethereumjs/lib/solidity/utils.js index 9ea416d8b..23566f74a 100644 --- a/libjsqrc/ethereumjs/lib/solidity/utils.js +++ b/libjsqrc/ethereumjs/lib/solidity/utils.js @@ -34,6 +34,11 @@ var getConstructor = function (abi, numberOfArgs) { })[0]; }; +//var getSupremeType = function (type) { + //return type.substr(0, type.indexOf('[')) + ']'; +//}; + + module.exports = { getConstructor: getConstructor }; diff --git a/libjsqrc/ethereumjs/lib/version.json b/libjsqrc/ethereumjs/lib/version.json index 536695767..e5c97ebab 100644 --- a/libjsqrc/ethereumjs/lib/version.json +++ b/libjsqrc/ethereumjs/lib/version.json @@ -1,3 +1,3 @@ { - "version": "0.3.3" + "version": "0.3.6" } diff --git a/libjsqrc/ethereumjs/lib/web3/eth.js b/libjsqrc/ethereumjs/lib/web3/eth.js index 625f5c02d..b955a45ac 100644 --- a/libjsqrc/ethereumjs/lib/web3/eth.js +++ b/libjsqrc/ethereumjs/lib/web3/eth.js @@ -23,7 +23,7 @@ /** * Web3 - * + * * @module web3 */ @@ -77,16 +77,16 @@ var uncleCountCall = function (args) { /// @returns an array of objects describing web3.eth api methods var getBalance = new Method({ - name: 'getBalance', - call: 'eth_getBalance', + name: 'getBalance', + call: 'eth_getBalance', params: 2, inputFormatter: [utils.toAddress, formatters.inputDefaultBlockNumberFormatter], outputFormatter: formatters.outputBigNumberFormatter }); var getStorageAt = new Method({ - name: 'getStorageAt', - call: 'eth_getStorageAt', + name: 'getStorageAt', + call: 'eth_getStorageAt', params: 3, inputFormatter: [null, utils.toHex, formatters.inputDefaultBlockNumberFormatter] }); @@ -99,7 +99,7 @@ var getCode = new Method({ }); var getBlock = new Method({ - name: 'getBlock', + name: 'getBlock', call: blockCall, params: 2, inputFormatter: [formatters.inputBlockNumberFormatter, function (val) { return !!val; }], @@ -224,6 +224,11 @@ var properties = [ name: 'mining', getter: 'eth_mining' }), + new Property({ + name: 'hashrate', + getter: 'eth_hashrate', + outputFormatter: utils.toDecimal + }), new Property({ name: 'gasPrice', getter: 'eth_gasPrice', diff --git a/libjsqrc/ethereumjs/lib/web3/event.js b/libjsqrc/ethereumjs/lib/web3/event.js index eeffa0cdd..f9305f8b8 100644 --- a/libjsqrc/ethereumjs/lib/web3/event.js +++ b/libjsqrc/ethereumjs/lib/web3/event.js @@ -96,7 +96,7 @@ SolidityEvent.prototype.encode = function (indexed, options) { ['fromBlock', 'toBlock'].filter(function (f) { return options[f] !== undefined; }).forEach(function (f) { - result[f] = utils.toHex(options[f]); + result[f] = formatters.inputBlockNumberFormatter(options[f]); }); result.topics = []; diff --git a/libjsqrc/ethereumjs/lib/web3/formatters.js b/libjsqrc/ethereumjs/lib/web3/formatters.js index 73fd907da..d45353649 100644 --- a/libjsqrc/ethereumjs/lib/web3/formatters.js +++ b/libjsqrc/ethereumjs/lib/web3/formatters.js @@ -72,7 +72,7 @@ var inputTransactionFormatter = function (options){ delete options.code; } - ['gasPrice', 'gas', 'value'].filter(function (key) { + ['gasPrice', 'gas', 'value', 'nonce'].filter(function (key) { return options[key] !== undefined; }).forEach(function(key){ options[key] = utils.fromDecimal(options[key]); diff --git a/libjsqrc/ethereumjs/lib/web3/httpprovider.js b/libjsqrc/ethereumjs/lib/web3/httpprovider.js index 83ab4bb5d..fd972c05a 100644 --- a/libjsqrc/ethereumjs/lib/web3/httpprovider.js +++ b/libjsqrc/ethereumjs/lib/web3/httpprovider.js @@ -48,15 +48,32 @@ HttpProvider.prototype.send = function (payload) { //if (request.status !== 200) { //return; //} - return JSON.parse(request.responseText); + + var result = request.responseText; + + try { + result = JSON.parse(result); + } catch(e) { + throw errors.InvalidResponse(result); + } + + return result; }; HttpProvider.prototype.sendAsync = function (payload, callback) { var request = new XMLHttpRequest(); request.onreadystatechange = function() { if (request.readyState === 4) { - // TODO: handle the error properly here!!! - callback(null, JSON.parse(request.responseText)); + var result = request.responseText; + var error = null; + + try { + result = JSON.parse(result); + } catch(e) { + error = errors.InvalidResponse(result); + } + + callback(error, result); } }; diff --git a/libjsqrc/ethereumjs/package.js b/libjsqrc/ethereumjs/package.js index 40b274bd7..bfb8d0556 100644 --- a/libjsqrc/ethereumjs/package.js +++ b/libjsqrc/ethereumjs/package.js @@ -1,7 +1,7 @@ /* jshint ignore:start */ Package.describe({ name: 'ethereum:web3', - version: '0.3.3', + version: '0.3.6', summary: 'Ethereum JavaScript API, middleware to talk to a ethreum node over RPC', git: 'https://github.com/ethereum/ethereum.js', // By default, Meteor will default to using README.md for documentation. diff --git a/libjsqrc/ethereumjs/package.json b/libjsqrc/ethereumjs/package.json index f6756cab1..4c7c81445 100644 --- a/libjsqrc/ethereumjs/package.json +++ b/libjsqrc/ethereumjs/package.json @@ -1,7 +1,7 @@ { "name": "web3", "namespace": "ethereum", - "version": "0.3.3", + "version": "0.3.6", "description": "Ethereum JavaScript API, middleware to talk to a ethereum node over RPC", "main": "./index.js", "directories": { diff --git a/libjsqrc/ethereumjs/test/abi.inputParser.js b/libjsqrc/ethereumjs/test/abi.inputParser.js deleted file mode 100644 index 6700acd72..000000000 --- a/libjsqrc/ethereumjs/test/abi.inputParser.js +++ /dev/null @@ -1,515 +0,0 @@ -var chai = require('chai'); -var assert = chai.assert; -var BigNumber = require('bignumber.js'); -var abi = require('../lib/solidity/abi'); -var clone = function (object) { return JSON.parse(JSON.stringify(object)); }; - -var description = [{ - "name": "test", - "type": "function", - "inputs": [{ - "name": "a", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "d", - "type": "uint256" - } - ] -}]; - -describe('lib/solidity/abi', function () { - describe('inputParser', function () { - it('should parse input uint', function () { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: "uint" } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); - assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); - assert.equal( - parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); - assert.equal( - parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); - assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); - assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); - assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); - assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); - - }); - - it('should parse input uint128', function() { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: "uint128" } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); - assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); - assert.equal( - parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); - assert.equal( - parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); - assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); - assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); - assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); - assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); - - }); - - it('should parse input uint256', function() { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: "uint256" } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); - assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); - assert.equal( - parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); - assert.equal( - parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); - assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); - assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); - assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); - assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); - - }); - - it('should parse input int', function() { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: "int" } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); - assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); - assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); - assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); - assert.equal( - parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); - assert.equal( - parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); - assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); - assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); - assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); - assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); - }); - - it('should parse input int128', function() { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: "int128" } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); - assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); - assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); - assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); - assert.equal( - parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); - assert.equal( - parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); - assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); - assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); - assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); - assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); - - }); - - it('should parse input int256', function() { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: "int256" } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); - assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); - assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); - assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); - assert.equal( - parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); - assert.equal( - parser.test(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)), - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ); - assert.equal(parser.test(0.1), "0000000000000000000000000000000000000000000000000000000000000000"); - assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); - assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); - assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); - - }); - - it('should parse input bool', function() { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: 'bool' } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal(parser.test(true), "0000000000000000000000000000000000000000000000000000000000000001"); - assert.equal(parser.test(false), "0000000000000000000000000000000000000000000000000000000000000000"); - - }); - - it('should parse input address', function () { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: "address" } - ]; - - // when - var parser = abi.inputParser(d) - - // then - assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); - - }); - - it('should parse input fixed bytes type', function () { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: "bytes" } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal( - parser.test('hello'), - "0000000000000000000000000000000000000000000000000000000000000005" + - "68656c6c6f000000000000000000000000000000000000000000000000000000" - ); - assert.equal( - parser.test('world'), - "0000000000000000000000000000000000000000000000000000000000000005776f726c64000000000000000000000000000000000000000000000000000000" - ); - }); - - it('should parse input int followed by a fixed bytes type', function () { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: "int" }, - { type: "bytes" } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal( - parser.test(9, 'hello'), - "0000000000000000000000000000000000000000000000000000000000000005" + - "0000000000000000000000000000000000000000000000000000000000000009" + - "68656c6c6f000000000000000000000000000000000000000000000000000000" - ); - }); - - it('should parse input fixed bytes type followed by an int', function () { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: "bytes" }, - { type: "int" } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal( - parser.test('hello', 9), - "0000000000000000000000000000000000000000000000000000000000000005" + - "0000000000000000000000000000000000000000000000000000000000000009" + - "68656c6c6f000000000000000000000000000000000000000000000000000000" - ); - }); - - it('should use proper method name', function () { - - // given - var d = clone(description); - d[0].name = 'helloworld(int)'; - d[0].inputs = [ - { type: "int" } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal(parser.helloworld(1), "0000000000000000000000000000000000000000000000000000000000000001"); - assert.equal(parser.helloworld['int'](1), "0000000000000000000000000000000000000000000000000000000000000001"); - - }); - - it('should parse multiple methods', function () { - - // given - var d = [{ - name: "test", - type: "function", - inputs: [{ type: "int" }], - outputs: [{ type: "int" }] - },{ - name: "test2", - type: "function", - inputs: [{ type: "bytes" }], - outputs: [{ type: "bytes" }] - }]; - - // when - var parser = abi.inputParser(d); - - //then - assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); - assert.equal( - parser.test2('hello'), - "000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000" - ); - - }); - - it('should parse input array of ints', function () { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: "int[]" } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal( - parser.test([5, 6]), - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "0000000000000000000000000000000000000000000000000000000000000006" - ); - }); - - it('should parse an array followed by an int', function () { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: "int[]" }, - { type: "int" } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal( - parser.test([5, 6], 3), - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000003" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "0000000000000000000000000000000000000000000000000000000000000006" - ); - }); - - it('should parse an int followed by an array', function () { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: "int" }, - { type: "int[]" } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal( - parser.test(3, [5, 6]), - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000003" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "0000000000000000000000000000000000000000000000000000000000000006" - ); - }); - - it('should parse mixture of arrays and ints', function () { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: "int" }, - { type: "int[]" }, - { type: "int" }, - { type: "int[]" } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal( - parser.test(3, [5, 6, 1, 2], 7, [8, 9]), - "0000000000000000000000000000000000000000000000000000000000000004" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000003" + - "0000000000000000000000000000000000000000000000000000000000000007" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "0000000000000000000000000000000000000000000000000000000000000006" + - "0000000000000000000000000000000000000000000000000000000000000001" + - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000008" + - "0000000000000000000000000000000000000000000000000000000000000009" - ); - }); - - it('should parse input real', function () { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: 'real' } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal(parser.test(1), "0000000000000000000000000000000100000000000000000000000000000000"); - assert.equal(parser.test(2.125), "0000000000000000000000000000000220000000000000000000000000000000"); - assert.equal(parser.test(8.5), "0000000000000000000000000000000880000000000000000000000000000000"); - assert.equal(parser.test(-1), "ffffffffffffffffffffffffffffffff00000000000000000000000000000000"); - - }); - - it('should parse input ureal', function () { - - // given - var d = clone(description); - - d[0].inputs = [ - { type: 'ureal' } - ]; - - // when - var parser = abi.inputParser(d); - - // then - assert.equal(parser.test(1), "0000000000000000000000000000000100000000000000000000000000000000"); - assert.equal(parser.test(2.125), "0000000000000000000000000000000220000000000000000000000000000000"); - assert.equal(parser.test(8.5), "0000000000000000000000000000000880000000000000000000000000000000"); - - }); - - it('should throw an incorrect type error', function () { - - // given - var d = clone(description); - d[0].inputs = [ - { type: 'uin' } - ] - - // when - var parser = abi.inputParser(d); - - // then - assert.throws(function () {parser.test('0x')}, Error); - - }); - - }); -}); diff --git a/libjsqrc/ethereumjs/test/abi.outputParser.js b/libjsqrc/ethereumjs/test/abi.outputParser.js deleted file mode 100644 index 5fe23e28a..000000000 --- a/libjsqrc/ethereumjs/test/abi.outputParser.js +++ /dev/null @@ -1,419 +0,0 @@ -var assert = require('assert'); -var BigNumber = require('bignumber.js'); -var abi = require('../lib/solidity/abi.js'); -var clone = function (object) { return JSON.parse(JSON.stringify(object)); }; - -var description = [{ - "name": "test", - "type": "function", - "inputs": [{ - "name": "a", - "type": "uint256" - } - ], - "outputs": [ - { - "name": "d", - "type": "uint256" - } - ] -}]; - -describe('lib/solidity/abi', function() { - describe('outputParser', function() { - it('should parse output fixed bytes type', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: "bytes" } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal( - parser.test( - "0000000000000000000000000000000000000000000000000000000000000005" + - "68656c6c6f000000000000000000000000000000000000000000000000000000")[0], - 'hello' - ); - assert.equal( - parser.test( - "0000000000000000000000000000000000000000000000000000000000000005" + - "776f726c64000000000000000000000000000000000000000000000000000000")[0], - 'world' - ); - - }); - - it('should parse output uint', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'uint' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000a")[0], 10); - assert.equal( - parser.test("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10), - new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10) - ); - assert.equal( - parser.test("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10), - new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10) - ); - }); - - it('should parse output uint256', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'uint256' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000a")[0], 10); - assert.equal( - parser.test("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10), - new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10) - ); - assert.equal( - parser.test("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10), - new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10) - ); - }); - - it('should parse output uint128', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'uint128' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000a")[0], 10); - assert.equal( - parser.test("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0].toString(10), - new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16).toString(10) - ); - assert.equal( - parser.test("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0].toString(10), - new BigNumber("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0", 16).toString(10) - ); - }); - - it('should parse output int', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'int' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000a")[0], 10); - assert.equal(parser.test("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1); - assert.equal(parser.test("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16); - }); - - it('should parse output int256', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'int256' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000a")[0], 10); - assert.equal(parser.test("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1); - assert.equal(parser.test("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16); - }); - - it('should parse output int128', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'int128' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.test("000000000000000000000000000000000000000000000000000000000000000a")[0], 10); - assert.equal(parser.test("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")[0], -1); - assert.equal(parser.test("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0")[0], -16); - }); - - it('should parse output address', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'address' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal( - parser.test("000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1")[0], - "0x407d73d8a49eeb85d32cf465507dd71d507100c1" - ); - }); - - it('should parse output bool', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'bool' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000001")[0], true); - assert.equal(parser.test("0000000000000000000000000000000000000000000000000000000000000000")[0], false); - - - }); - - it('should parse output real', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'real' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0000000000000000000000000000000100000000000000000000000000000000")[0], 1); - assert.equal(parser.test("0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125); - assert.equal(parser.test("0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5); - assert.equal(parser.test("ffffffffffffffffffffffffffffffff00000000000000000000000000000000")[0], -1); - - }); - - it('should parse output ureal', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: 'ureal' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0000000000000000000000000000000100000000000000000000000000000000")[0], 1); - assert.equal(parser.test("0000000000000000000000000000000220000000000000000000000000000000")[0], 2.125); - assert.equal(parser.test("0000000000000000000000000000000880000000000000000000000000000000")[0], 8.5); - - }); - - - it('should parse multiple output fixed bytes type', function() { - - // given - var d = clone(description); - - d[0].outputs = [ - { type: "bytes" }, - { type: "bytes" } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal( - parser.test( - "0000000000000000000000000000000000000000000000000000000000000005" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "68656c6c6f000000000000000000000000000000000000000000000000000000" + - "776f726c64000000000000000000000000000000000000000000000000000000")[0], - 'hello' - ); - assert.equal( - parser.test( - "0000000000000000000000000000000000000000000000000000000000000005" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "68656c6c6f000000000000000000000000000000000000000000000000000000" + - "776f726c64000000000000000000000000000000000000000000000000000000")[1], - 'world' - ); - - }); - - it('should use proper method name', function () { - - // given - var d = clone(description); - d[0].name = 'helloworld(int)'; - d[0].outputs = [ - { type: "int" } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.helloworld("0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.helloworld['int']("0000000000000000000000000000000000000000000000000000000000000001")[0], 1); - - }); - - - it('should parse multiple methods', function () { - - // given - var d = [{ - name: "test", - type: "function", - inputs: [{ type: "int" }], - outputs: [{ type: "int" }] - },{ - name: "test2", - type: "function", - inputs: [{ type: "bytes" }], - outputs: [{ type: "bytes" }] - }]; - - // when - var parser = abi.outputParser(d); - - //then - assert.equal(parser.test("00000000000000000000000000000000000000000000000000000000000001")[0], 1); - assert.equal(parser.test2( - "0000000000000000000000000000000000000000000000000000000000000005" + - "68656c6c6f000000000000000000000000000000000000000000000000000000")[0], - "hello" - ); - - }); - - it('should parse output array', function () { - - // given - var d = clone(description); - d[0].outputs = [ - { type: 'int[]' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test( - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "0000000000000000000000000000000000000000000000000000000000000006")[0][0], - 5 - ); - assert.equal(parser.test( - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000005" + - "0000000000000000000000000000000000000000000000000000000000000006")[0][1], - 6 - ); - - }); - - it('should parse 0x0 value', function () { - - // given - var d = clone(description); - d[0].outputs = [ - { type: 'int' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0x0")[0], 0); - - }); - - it('should parse 0x0 value', function () { - - // given - var d = clone(description); - d[0].outputs = [ - { type: 'uint' } - ]; - - // when - var parser = abi.outputParser(d); - - // then - assert.equal(parser.test("0x0")[0], 0); - - }); - - it('should throw an incorrect type error', function () { - - // given - var d = clone(description); - d[0].outputs = [ - { type: 'uin' } - ] - - // when - var parser = abi.outputParser(d); - - // then - assert.throws(function () {parser.test('0x')}, Error); - - }); - - }); -}); - diff --git a/libjsqrc/ethereumjs/test/coder.decodeParam.js b/libjsqrc/ethereumjs/test/coder.decodeParam.js index 3eea9dd6f..23b0228eb 100644 --- a/libjsqrc/ethereumjs/test/coder.decodeParam.js +++ b/libjsqrc/ethereumjs/test/coder.decodeParam.js @@ -21,17 +21,32 @@ describe('lib/solidity/coder', function () { test({ type: 'int256', expected: new bn(16), value: '0000000000000000000000000000000000000000000000000000000000000010'}); test({ type: 'int256', expected: new bn(-1), value: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); test({ type: 'bytes32', expected: 'gavofyork', value: '6761766f66796f726b0000000000000000000000000000000000000000000000'}); - test({ type: 'bytes', expected: 'gavofyork', value: '0000000000000000000000000000000000000000000000000000000000000009' + + test({ type: 'bytes', expected: 'gavofyork', value: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000009' + '6761766f66796f726b0000000000000000000000000000000000000000000000'}); - test({ type: 'int[]', expected: [new bn(3)], value: '0000000000000000000000000000000000000000000000000000000000000001' + + test({ type: 'int[]', expected: [new bn(3)], value: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000001' + '0000000000000000000000000000000000000000000000000000000000000003'}); - test({ type: 'int256[]', expected: [new bn(3)], value: '0000000000000000000000000000000000000000000000000000000000000001' + + test({ type: 'int256[]', expected: [new bn(3)], value: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000001' + '0000000000000000000000000000000000000000000000000000000000000003'}); test({ type: 'int[]', expected: [new bn(1), new bn(2), new bn(3)], - value: '0000000000000000000000000000000000000000000000000000000000000003' + + value: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000003' + '0000000000000000000000000000000000000000000000000000000000000001' + '0000000000000000000000000000000000000000000000000000000000000002' + '0000000000000000000000000000000000000000000000000000000000000003'}); + test({ type: 'bool', expected: true, value: '0000000000000000000000000000000000000000000000000000000000000001'}); + test({ type: 'bool', expected: false, value: '0000000000000000000000000000000000000000000000000000000000000000'}); + test({ type: 'real', expected: new bn(1), value: '0000000000000000000000000000000100000000000000000000000000000000'}); + test({ type: 'real', expected: new bn(2.125), value: '0000000000000000000000000000000220000000000000000000000000000000'}); + test({ type: 'real', expected: new bn(8.5), value: '0000000000000000000000000000000880000000000000000000000000000000'}); + test({ type: 'real', expected: new bn(-1), value: 'ffffffffffffffffffffffffffffffff00000000000000000000000000000000'}); + test({ type: 'ureal', expected: new bn(1), value: '0000000000000000000000000000000100000000000000000000000000000000'}); + test({ type: 'ureal', expected: new bn(2.125), value: '0000000000000000000000000000000220000000000000000000000000000000'}); + test({ type: 'ureal', expected: new bn(8.5), value: '0000000000000000000000000000000880000000000000000000000000000000'}); + test({ type: 'address', expected: '0x407d73d8a49eeb85d32cf465507dd71d507100c1', + value: '000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1'}); }); }); @@ -53,16 +68,18 @@ describe('lib/solidity/coder', function () { '6761766f66796f726b0000000000000000000000000000000000000000000000'}); test({ types: ['int', 'bytes', 'int', 'int', 'int', 'int[]'], expected: [new bn(1), 'gavofyork', new bn(2), new bn(3), new bn(4), [new bn(5), new bn(6), new bn(7)]], - values: '0000000000000000000000000000000000000000000000000000000000000009' + - '0000000000000000000000000000000000000000000000000000000000000003' + - '0000000000000000000000000000000000000000000000000000000000000001' + - '0000000000000000000000000000000000000000000000000000000000000002' + - '0000000000000000000000000000000000000000000000000000000000000003' + - '0000000000000000000000000000000000000000000000000000000000000004' + - '6761766f66796f726b0000000000000000000000000000000000000000000000' + - '0000000000000000000000000000000000000000000000000000000000000005' + - '0000000000000000000000000000000000000000000000000000000000000006' + - '0000000000000000000000000000000000000000000000000000000000000007'}); + values: '0000000000000000000000000000000000000000000000000000000000000001' + + '00000000000000000000000000000000000000000000000000000000000000c0' + + '0000000000000000000000000000000000000000000000000000000000000002' + + '0000000000000000000000000000000000000000000000000000000000000003' + + '0000000000000000000000000000000000000000000000000000000000000004' + + '0000000000000000000000000000000000000000000000000000000000000100' + + '0000000000000000000000000000000000000000000000000000000000000009' + + '6761766f66796f726b0000000000000000000000000000000000000000000000' + + '0000000000000000000000000000000000000000000000000000000000000003' + + '0000000000000000000000000000000000000000000000000000000000000005' + + '0000000000000000000000000000000000000000000000000000000000000006' + + '0000000000000000000000000000000000000000000000000000000000000007'}); }); }); diff --git a/libjsqrc/ethereumjs/test/coder.encodeParam.js b/libjsqrc/ethereumjs/test/coder.encodeParam.js index a9e11ab9e..60d1c618e 100644 --- a/libjsqrc/ethereumjs/test/coder.encodeParam.js +++ b/libjsqrc/ethereumjs/test/coder.encodeParam.js @@ -15,20 +15,37 @@ describe('lib/solidity/coder', function () { test({ type: 'int', value: 1, expected: '0000000000000000000000000000000000000000000000000000000000000001'}); test({ type: 'int', value: 16, expected: '0000000000000000000000000000000000000000000000000000000000000010'}); test({ type: 'int', value: -1, expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); + test({ type: 'int', value: 0.1, expected: '0000000000000000000000000000000000000000000000000000000000000000'}); + test({ type: 'int', value: 3.9, expected: '0000000000000000000000000000000000000000000000000000000000000003'}); test({ type: 'int256', value: 1, expected: '0000000000000000000000000000000000000000000000000000000000000001'}); test({ type: 'int256', value: 16, expected: '0000000000000000000000000000000000000000000000000000000000000010'}); test({ type: 'int256', value: -1, expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); test({ type: 'bytes32', value: 'gavofyork', expected: '6761766f66796f726b0000000000000000000000000000000000000000000000'}); - test({ type: 'bytes', value: 'gavofyork', expected: '0000000000000000000000000000000000000000000000000000000000000009' + + test({ type: 'bytes', value: 'gavofyork', expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000009' + '6761766f66796f726b0000000000000000000000000000000000000000000000'}); - test({ type: 'int[]', value: [3], expected: '0000000000000000000000000000000000000000000000000000000000000001' + + test({ type: 'int[]', value: [3], expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000001' + '0000000000000000000000000000000000000000000000000000000000000003'}); - test({ type: 'int256[]', value: [3], expected: '0000000000000000000000000000000000000000000000000000000000000001' + + test({ type: 'int256[]', value: [3], expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000001' + '0000000000000000000000000000000000000000000000000000000000000003'}); - test({ type: 'int[]', value: [1,2,3], expected: '0000000000000000000000000000000000000000000000000000000000000003' + + test({ type: 'int[]', value: [1,2,3], expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000003' + '0000000000000000000000000000000000000000000000000000000000000001' + '0000000000000000000000000000000000000000000000000000000000000002' + '0000000000000000000000000000000000000000000000000000000000000003'}); + test({ type: 'bool', value: true, expected: '0000000000000000000000000000000000000000000000000000000000000001'}); + test({ type: 'bool', value: false, expected: '0000000000000000000000000000000000000000000000000000000000000000'}); + test({ type: 'address', value: '0x407d73d8a49eeb85d32cf465507dd71d507100c1', + expected: '000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1'}); + test({ type: 'real', value: 1, expected: '0000000000000000000000000000000100000000000000000000000000000000'}); + test({ type: 'real', value: 2.125, expected: '0000000000000000000000000000000220000000000000000000000000000000'}); + test({ type: 'real', value: 8.5, expected: '0000000000000000000000000000000880000000000000000000000000000000'}); + test({ type: 'real', value: -1, expected: 'ffffffffffffffffffffffffffffffff00000000000000000000000000000000'}); + test({ type: 'ureal', value: 1, expected: '0000000000000000000000000000000100000000000000000000000000000000'}); + test({ type: 'ureal', value: 2.125, expected: '0000000000000000000000000000000220000000000000000000000000000000'}); + test({ type: 'ureal', value: 8.5, expected: '0000000000000000000000000000000880000000000000000000000000000000'}); }); }); @@ -49,16 +66,29 @@ describe('lib/solidity/coder', function () { test({ types: ['int256'], values: [16], expected: '0000000000000000000000000000000000000000000000000000000000000010'}); test({ types: ['int256'], values: [-1], expected: 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'}); test({ types: ['bytes32'], values: ['gavofyork'], expected: '6761766f66796f726b0000000000000000000000000000000000000000000000'}); - test({ types: ['bytes'], values: ['gavofyork'], expected: '0000000000000000000000000000000000000000000000000000000000000009' + + test({ types: ['bytes'], values: ['gavofyork'], expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000009' + '6761766f66796f726b0000000000000000000000000000000000000000000000'}); - test({ types: ['int[]'], values: [[3]], expected: '0000000000000000000000000000000000000000000000000000000000000001' + + test({ types: ['int[]'], values: [[3]], expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000001' + '0000000000000000000000000000000000000000000000000000000000000003'}); - test({ types: ['int256[]'], values: [[3]], expected: '0000000000000000000000000000000000000000000000000000000000000001' + + test({ types: ['int256[]'], values: [[3]], expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000001' + '0000000000000000000000000000000000000000000000000000000000000003'}); - test({ types: ['int256[]'], values: [[1,2,3]], expected: '0000000000000000000000000000000000000000000000000000000000000003' + + test({ types: ['int256[]'], values: [[1,2,3]], expected: '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000003' + '0000000000000000000000000000000000000000000000000000000000000001' + '0000000000000000000000000000000000000000000000000000000000000002' + '0000000000000000000000000000000000000000000000000000000000000003'}); + test({ types: ['int[]', 'int[]'], values: [[1,2], [3,4]], + expected: '0000000000000000000000000000000000000000000000000000000000000040' + + '00000000000000000000000000000000000000000000000000000000000000a0' + + '0000000000000000000000000000000000000000000000000000000000000002' + + '0000000000000000000000000000000000000000000000000000000000000001' + + '0000000000000000000000000000000000000000000000000000000000000002' + + '0000000000000000000000000000000000000000000000000000000000000002' + + '0000000000000000000000000000000000000000000000000000000000000003' + + '0000000000000000000000000000000000000000000000000000000000000004'}); test({ types: ['bytes32', 'int'], values: ['gavofyork', 5], expected: '6761766f66796f726b0000000000000000000000000000000000000000000000' + '0000000000000000000000000000000000000000000000000000000000000005'}); @@ -66,25 +96,47 @@ describe('lib/solidity/coder', function () { expected: '0000000000000000000000000000000000000000000000000000000000000005' + '6761766f66796f726b0000000000000000000000000000000000000000000000'}); test({ types: ['bytes', 'int'], values: ['gavofyork', 5], - expected: '0000000000000000000000000000000000000000000000000000000000000009' + + expected: '0000000000000000000000000000000000000000000000000000000000000040' + '0000000000000000000000000000000000000000000000000000000000000005' + + '0000000000000000000000000000000000000000000000000000000000000009' + '6761766f66796f726b0000000000000000000000000000000000000000000000'}); + test({ types: ['bytes', 'bool', 'int[]'], values: ['gavofyork', true, [1, 2, 3]], + expected: '0000000000000000000000000000000000000000000000000000000000000060' + + '0000000000000000000000000000000000000000000000000000000000000001' + + '00000000000000000000000000000000000000000000000000000000000000a0' + + '0000000000000000000000000000000000000000000000000000000000000009' + + '6761766f66796f726b0000000000000000000000000000000000000000000000' + + '0000000000000000000000000000000000000000000000000000000000000003' + + '0000000000000000000000000000000000000000000000000000000000000001' + + '0000000000000000000000000000000000000000000000000000000000000002' + + '0000000000000000000000000000000000000000000000000000000000000003'}); + test({ types: ['bytes', 'int[]'], values: ['gavofyork', [1, 2, 3]], + expected: '0000000000000000000000000000000000000000000000000000000000000040' + + '0000000000000000000000000000000000000000000000000000000000000080' + + '0000000000000000000000000000000000000000000000000000000000000009' + + '6761766f66796f726b0000000000000000000000000000000000000000000000' + + '0000000000000000000000000000000000000000000000000000000000000003' + + '0000000000000000000000000000000000000000000000000000000000000001' + + '0000000000000000000000000000000000000000000000000000000000000002' + + '0000000000000000000000000000000000000000000000000000000000000003'}); test({ types: ['int', 'bytes'], values: [5, 'gavofyork'], - expected: '0000000000000000000000000000000000000000000000000000000000000009' + - '0000000000000000000000000000000000000000000000000000000000000005' + + expected: '0000000000000000000000000000000000000000000000000000000000000005' + + '0000000000000000000000000000000000000000000000000000000000000040' + + '0000000000000000000000000000000000000000000000000000000000000009' + '6761766f66796f726b0000000000000000000000000000000000000000000000'}); test({ types: ['int', 'bytes', 'int', 'int', 'int', 'int[]'], values: [1, 'gavofyork', 2, 3, 4, [5, 6, 7]], - expected: '0000000000000000000000000000000000000000000000000000000000000009' + - '0000000000000000000000000000000000000000000000000000000000000003' + - '0000000000000000000000000000000000000000000000000000000000000001' + + expected: '0000000000000000000000000000000000000000000000000000000000000001' + + '00000000000000000000000000000000000000000000000000000000000000c0' + '0000000000000000000000000000000000000000000000000000000000000002' + '0000000000000000000000000000000000000000000000000000000000000003' + '0000000000000000000000000000000000000000000000000000000000000004' + + '0000000000000000000000000000000000000000000000000000000000000100' + + '0000000000000000000000000000000000000000000000000000000000000009' + '6761766f66796f726b0000000000000000000000000000000000000000000000' + + '0000000000000000000000000000000000000000000000000000000000000003' + '0000000000000000000000000000000000000000000000000000000000000005' + '0000000000000000000000000000000000000000000000000000000000000006' + '0000000000000000000000000000000000000000000000000000000000000007'}); - }); }); diff --git a/libjsqrc/ethereumjs/test/contract.js b/libjsqrc/ethereumjs/test/contract.js index 8a2ea109d..0dcaa1003 100644 --- a/libjsqrc/ethereumjs/test/contract.js +++ b/libjsqrc/ethereumjs/test/contract.js @@ -345,6 +345,7 @@ describe('web3.eth.contract', function () { assert.equal(payload.method, 'eth_call'); assert.deepEqual(payload.params, [{ data: sha3.slice(0, 10) + + '0000000000000000000000000000000000000000000000000000000000000020' + '0000000000000000000000000000000000000000000000000000000000000001' + '0000000000000000000000000000000000000000000000000000000000000003', to: address diff --git a/libjsqrc/ethereumjs/test/event.encode.js b/libjsqrc/ethereumjs/test/event.encode.js index c28588c2e..6d9850c00 100644 --- a/libjsqrc/ethereumjs/test/event.encode.js +++ b/libjsqrc/ethereumjs/test/event.encode.js @@ -119,6 +119,32 @@ var tests = [{ ] } }, { + abi: { + name: 'event1', + inputs: [{ + type: 'int', + name: 'a', + indexed: true + }] + }, + indexed: { + a: 1 + }, + options: { + fromBlock: 'latest', + toBlock: 'pending' + }, + expected: { + address: address, + fromBlock: 'latest', + toBlock: 'pending', + topics: [ + signature, + '0x0000000000000000000000000000000000000000000000000000000000000001' + ] + } +}, +{ abi: { name: 'event1', inputs: [{ diff --git a/libjsqrc/ethereumjs/test/formatters.inputTransactionFormatter.js b/libjsqrc/ethereumjs/test/formatters.inputTransactionFormatter.js index 2f7f8c2e5..44c3534d3 100644 --- a/libjsqrc/ethereumjs/test/formatters.inputTransactionFormatter.js +++ b/libjsqrc/ethereumjs/test/formatters.inputTransactionFormatter.js @@ -3,24 +3,62 @@ var assert = chai.assert; var formatters = require('../lib/web3/formatters.js'); var BigNumber = require('bignumber.js'); +var tests = [{ + input: { + data: '0x34234bf23bf4234', + value: new BigNumber(100), + from: '0x00000', + to: '0x00000', + nonce: 1000, + gas: 1000, + gasPrice: new BigNumber(1000) + }, + result: { + data: '0x34234bf23bf4234', + value: '0x64', + from: '0x00000', + to: '0x00000', + nonce: '0x3e8', + gas: '0x3e8', + gasPrice: '0x3e8' + } +},{ + input: { + data: '0x34234bf23bf4234', + value: new BigNumber(100), + from: '0x00000', + to: '0x00000', + }, + result: { + data: '0x34234bf23bf4234', + value: '0x64', + from: '0x00000', + to: '0x00000', + } +},{ + input: { + data: '0x34234bf23bf4234', + value: new BigNumber(100), + from: '0x00000', + to: '0x00000', + gas: '1000', + gasPrice: new BigNumber(1000) + }, + result: { + data: '0x34234bf23bf4234', + value: '0x64', + from: '0x00000', + to: '0x00000', + gas: '0x3e8', + gasPrice: '0x3e8' + } +}]; + describe('formatters', function () { describe('inputTransactionFormatter', function () { - it('should return the correct value', function () { - - assert.deepEqual(formatters.inputTransactionFormatter({ - data: '0x34234bf23bf4234', - value: new BigNumber(100), - from: '0x00000', - to: '0x00000', - gas: 1000, - gasPrice: new BigNumber(1000) - }), { - data: '0x34234bf23bf4234', - value: '0x64', - from: '0x00000', - to: '0x00000', - gas: '0x3e8', - gasPrice: '0x3e8' + tests.forEach(function(test){ + it('should return the correct value', function () { + assert.deepEqual(formatters.inputTransactionFormatter(test.input), test.result); }); }); }); diff --git a/libjsqrc/ethereumjs/test/web3.eth.filter.js b/libjsqrc/ethereumjs/test/web3.eth.filter.js index d8b37311a..7a355b50c 100644 --- a/libjsqrc/ethereumjs/test/web3.eth.filter.js +++ b/libjsqrc/ethereumjs/test/web3.eth.filter.js @@ -21,6 +21,21 @@ var tests = [{ result: '0xf', formattedResult: '0xf', call: 'eth_newFilter' +},{ + args: [{ + fromBlock: 'latest', + toBlock: 'latest', + address: '0x47d33b27bb249a2dbab4c0612bf9caf4c1950855' + }], + formattedArgs: [{ + fromBlock: 'latest', + toBlock: 'latest', + address: '0x47d33b27bb249a2dbab4c0612bf9caf4c1950855', + topics: [] + }], + result: '0xf', + formattedResult: '0xf', + call: 'eth_newFilter' },{ args: ['pending'], formattedArgs: ['pending'], diff --git a/libjsqrc/ethereumjs/test/web3.eth.hashRate.js b/libjsqrc/ethereumjs/test/web3.eth.hashRate.js new file mode 100644 index 000000000..ec01bfad1 --- /dev/null +++ b/libjsqrc/ethereumjs/test/web3.eth.hashRate.js @@ -0,0 +1,38 @@ +var chai = require('chai'); +var assert = chai.assert; +var web3 = require('../index'); +var FakeHttpProvider = require('./helpers/FakeHttpProvider'); + +var method = 'hashrate'; + +var tests = [{ + result: '0x788a8', + formattedResult: 493736, + call: 'eth_'+ method +}]; + +describe('web3.eth', function () { + describe(method, function () { + tests.forEach(function (test, index) { + it('property test: ' + index, function () { + + // given + var provider = new FakeHttpProvider(); + web3.setProvider(provider); + provider.injectResult(test.result); + provider.injectValidation(function (payload) { + assert.equal(payload.jsonrpc, '2.0'); + assert.equal(payload.method, test.call); + assert.deepEqual(payload.params, []); + }); + + // when + var result = web3.eth[method]; + + // then + assert.strictEqual(test.formattedResult, result); + }); + }); + }); +}); + diff --git a/libp2p/Common.cpp b/libp2p/Common.cpp index f4394b146..ed84f014c 100644 --- a/libp2p/Common.cpp +++ b/libp2p/Common.cpp @@ -24,8 +24,9 @@ using namespace std; using namespace dev; using namespace dev::p2p; -const unsigned dev::p2p::c_protocolVersion = 3; +const unsigned dev::p2p::c_protocolVersion = 4; const unsigned dev::p2p::c_defaultIPPort = 30303; +static_assert(dev::p2p::c_protocolVersion == 4, "Replace v3 compatbility with v4 compatibility before updating network version."); const dev::p2p::NodeIPEndpoint dev::p2p::UnspecifiedNodeIPEndpoint = NodeIPEndpoint(bi::address(), 0, 0); const dev::p2p::Node dev::p2p::UnspecifiedNode = dev::p2p::Node(NodeId(), UnspecifiedNodeIPEndpoint); @@ -144,6 +145,31 @@ std::string p2p::reasonOf(DisconnectReason _r) } } +void NodeIPEndpoint::streamRLP(RLPStream& _s, RLPAppend _append) const +{ + if (_append == StreamList) + _s.appendList(3); + if (address.is_v4()) + _s << bytesConstRef(&address.to_v4().to_bytes()[0], 4); + else if (address.is_v6()) + _s << bytesConstRef(&address.to_v6().to_bytes()[0], 16); + else + _s << bytes(); + _s << udpPort << tcpPort; +} + +void NodeIPEndpoint::interpretRLP(RLP const& _r) +{ + if (_r[0].size() == 4) + address = bi::address_v4(*(bi::address_v4::bytes_type*)_r[0].toBytes().data()); + else if (_r[0].size() == 16) + address = bi::address_v6(*(bi::address_v6::bytes_type*)_r[0].toBytes().data()); + else + address = bi::address(); + udpPort = _r[1].toInt(); + tcpPort = _r[2].toInt(); +} + namespace dev { std::ostream& operator<<(std::ostream& _out, dev::p2p::NodeIPEndpoint const& _ep) diff --git a/libp2p/Common.h b/libp2p/Common.h index 378064e7d..da7558ecb 100644 --- a/libp2p/Common.h +++ b/libp2p/Common.h @@ -36,6 +36,7 @@ #include #include #include +#include namespace ba = boost::asio; namespace bi = boost::asio::ip; @@ -162,10 +163,17 @@ using PeerSessionInfos = std::vector; */ struct NodeIPEndpoint { + enum RLPAppend + { + StreamList, + StreamInline + }; + /// Setting true causes isAllowed to return true for all addresses. (Used by test fixtures) static bool test_allowLocal; NodeIPEndpoint(bi::address _addr, uint16_t _udp, uint16_t _tcp): address(_addr), udpPort(_udp), tcpPort(_tcp) {} + NodeIPEndpoint(RLP const& _r) { interpretRLP(_r); } bi::address address; uint16_t udpPort; @@ -177,11 +185,14 @@ struct NodeIPEndpoint operator bool() const { return !address.is_unspecified() && udpPort > 0 && tcpPort > 0; } bool isAllowed() const { return NodeIPEndpoint::test_allowLocal ? !address.is_unspecified() : isPublicAddress(address); } + + void streamRLP(RLPStream& _s, RLPAppend _append = StreamList) const; + void interpretRLP(RLP const& _r); }; struct Node { - Node(Public _pubk, NodeIPEndpoint _ip, bool _required = false): id(_pubk), endpoint(_ip), required(_required) {} + Node(Public _pubk, NodeIPEndpoint const& _ip, bool _required = false): id(_pubk), endpoint(_ip), required(_required) {} virtual NodeId const& address() const { return id; } virtual Public const& publicKey() const { return id; } @@ -203,3 +214,26 @@ struct Node /// Simple stream output for a NodeIPEndpoint. std::ostream& operator<<(std::ostream& _out, dev::p2p::NodeIPEndpoint const& _ep); } + +/// std::hash for asio::adress +namespace std +{ + +template <> struct hash +{ + size_t operator()(bi::address const& _a) const + { + if (_a.is_v4()) + return std::hash()(_a.to_v4().to_ulong()); + if (_a.is_v6()) + { + auto const& range = _a.to_v6().to_bytes(); + return boost::hash_range(range.begin(), range.end()); + } + if (_a.is_unspecified()) + return static_cast(0x3487194039229152ul); // Chosen by fair dice roll, guaranteed to be random + return std::hash()(_a.to_string()); + } +}; + +} diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 8ba04b0e7..9b5a6dca7 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -208,7 +208,7 @@ void Host::startPeerSession(Public const& _id, RLP const& _rlp, RLPXFrameIO* _io // create session so disconnects are managed auto ps = make_shared(this, _io, p, PeerSessionInfo({_id, clientVersion, _endpoint.address().to_string(), listenPort, chrono::steady_clock::duration(), _rlp[2].toSet(), 0, map()})); - if (protocolVersion < dev::p2p::c_protocolVersion) + if (protocolVersion < dev::p2p::c_protocolVersion - 1) { ps->disconnect(IncompatibleProtocol); return; @@ -389,6 +389,16 @@ string Host::pocHost() return "poc-" + strs[1] + ".ethdev.com"; } +std::unordered_map const& Host::pocHosts() +{ + static const std::unordered_map c_ret = { +// { Public(""), "poc-9.ethdev.com:30303" }, + { Public("a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c"), "52.16.188.185:30303" }, + { Public("7f25d3eab333a6b98a8b5ed68d962bb22c876ffcd5561fca54e3c2ef27f754df6f7fd7c9b74cc919067abac154fb8e1f8385505954f161ae440abc355855e034"), "54.207.93.166:30303" } + }; + return c_ret; +} + void Host::addNode(NodeId const& _node, NodeIPEndpoint const& _endpoint) { // return if network is stopped while waiting on Host::run() or nodeTable to start @@ -696,15 +706,16 @@ bytes Host::saveNetwork() const int count = 0; for (auto const& p: peers) { - // Only save peers which have connected within 2 days, with properly-advertised port and public IP address - // todo: e2e ipv6 support + // todo: ipv6 if (!p.endpoint.address.is_v4()) continue; - if (chrono::system_clock::now() - p.m_lastConnected < chrono::seconds(3600 * 48) && p.endpoint.tcpPort > 0 && p.id != id() && (p.required || p.endpoint.isAllowed())) + // Only save peers which have connected within 2 days, with properly-advertised port and public IP address + if (chrono::system_clock::now() - p.m_lastConnected < chrono::seconds(3600 * 48) && !!p.endpoint && p.id != id() && (p.required || p.endpoint.isAllowed())) { - network.appendList(10); - network << p.endpoint.address.to_v4().to_bytes() << p.endpoint.tcpPort << p.id << p.required + network.appendList(11); + p.endpoint.streamRLP(network, NodeIPEndpoint::StreamInline); + network << p.id << p.required << chrono::duration_cast(p.m_lastConnected.time_since_epoch()).count() << chrono::duration_cast(p.m_lastAttempted.time_since_epoch()).count() << p.m_failedAttempts << (unsigned)p.m_lastDisconnect << p.m_score << p.m_rating; @@ -718,12 +729,9 @@ bytes Host::saveNetwork() const state.sort(); for (auto const& entry: state) { - network.appendList(3); - if (entry.endpoint.address.is_v4()) - network << entry.endpoint.address.to_v4().to_bytes(); - else - network << entry.endpoint.address.to_v6().to_bytes(); - network << entry.endpoint.tcpPort << entry.id; + network.appendList(4); + entry.endpoint.streamRLP(network, NodeIPEndpoint::StreamInline); + network << entry.id; count++; } } @@ -739,6 +747,9 @@ bytes Host::saveNetwork() const void Host::restoreNetwork(bytesConstRef _b) { + if (!_b.size()) + return; + // nodes can only be added if network is added if (!isStarted()) BOOST_THROW_EXCEPTION(NetworkStartRequired()); @@ -748,7 +759,8 @@ void Host::restoreNetwork(bytesConstRef _b) RecursiveGuard l(x_sessions); RLP r(_b); - if (r.itemCount() > 0 && r[0].isInt() && r[0].toInt() == dev::p2p::c_protocolVersion) + unsigned fileVersion = r[0].toInt(); + if (r.itemCount() > 0 && r[0].isInt() && fileVersion >= dev::p2p::c_protocolVersion - 1) { // r[0] = version // r[1] = key @@ -756,30 +768,57 @@ void Host::restoreNetwork(bytesConstRef _b) for (auto i: r[2]) { - if (i[0].itemCount() != 4) + // todo: ipv6 + if (i[0].itemCount() != 4 && i[0].size() != 4) continue; - - // todo: ipv6, bi::address_v6(i[0].toArray() - Node n((NodeId)i[2], NodeIPEndpoint(bi::address_v4(i[0].toArray()), i[1].toInt(), i[1].toInt())); - if (i.itemCount() == 3 && n.endpoint.isAllowed()) - m_nodeTable->addNode(n, NodeTable::NodeRelation::Known); - else if (i.itemCount() == 10) + + if (i.itemCount() == 4 || i.itemCount() == 11) { - n.required = i[3].toInt(); - if (!n.endpoint.isAllowed() && !n.required) - continue; - shared_ptr p = make_shared(n); - p->m_lastConnected = chrono::system_clock::time_point(chrono::seconds(i[4].toInt())); - p->m_lastAttempted = chrono::system_clock::time_point(chrono::seconds(i[5].toInt())); - p->m_failedAttempts = i[6].toInt(); - p->m_lastDisconnect = (DisconnectReason)i[7].toInt(); - p->m_score = (int)i[8].toInt(); - p->m_rating = (int)i[9].toInt(); - m_peers[p->id] = p; - if (p->required) - requirePeer(p->id, n.endpoint); - else - m_nodeTable->addNode(*p.get(), NodeTable::NodeRelation::Known); + Node n((NodeId)i[3], NodeIPEndpoint(i)); + if (i.itemCount() == 4 && n.endpoint.isAllowed()) + m_nodeTable->addNode(n); + else if (i.itemCount() == 11) + { + n.required = i[4].toInt(); + if (!n.endpoint.isAllowed() && !n.required) + continue; + shared_ptr p = make_shared(n); + p->m_lastConnected = chrono::system_clock::time_point(chrono::seconds(i[5].toInt())); + p->m_lastAttempted = chrono::system_clock::time_point(chrono::seconds(i[6].toInt())); + p->m_failedAttempts = i[7].toInt(); + p->m_lastDisconnect = (DisconnectReason)i[8].toInt(); + p->m_score = (int)i[9].toInt(); + p->m_rating = (int)i[10].toInt(); + m_peers[p->id] = p; + if (p->required) + requirePeer(p->id, n.endpoint); + else + m_nodeTable->addNode(*p.get(), NodeTable::NodeRelation::Known); + } + } + else if (i.itemCount() == 3 || i.itemCount() == 10) + { + Node n((NodeId)i[2], NodeIPEndpoint(bi::address_v4(i[0].toArray()), i[1].toInt(), i[1].toInt())); + if (i.itemCount() == 3 && n.endpoint.isAllowed()) + m_nodeTable->addNode(n); + else if (i.itemCount() == 10) + { + n.required = i[3].toInt(); + if (!n.endpoint.isAllowed() && !n.required) + continue; + shared_ptr p = make_shared(n); + p->m_lastConnected = chrono::system_clock::time_point(chrono::seconds(i[4].toInt())); + p->m_lastAttempted = chrono::system_clock::time_point(chrono::seconds(i[5].toInt())); + p->m_failedAttempts = i[6].toInt(); + p->m_lastDisconnect = (DisconnectReason)i[7].toInt(); + p->m_score = (int)i[8].toInt(); + p->m_rating = (int)i[9].toInt(); + m_peers[p->id] = p; + if (p->required) + requirePeer(p->id, n.endpoint); + else + m_nodeTable->addNode(*p.get(), NodeTable::NodeRelation::Known); + } } } } @@ -788,7 +827,7 @@ void Host::restoreNetwork(bytesConstRef _b) KeyPair Host::networkAlias(bytesConstRef _b) { RLP r(_b); - if (r.itemCount() == 3 && r[0].isInt() && r[0].toInt() == dev::p2p::c_protocolVersion) + if (r.itemCount() == 3 && r[0].isInt() && r[0].toInt() >= 3) return move(KeyPair(move(Secret(r[1].toBytes())))); else return move(KeyPair::create()); diff --git a/libp2p/Host.h b/libp2p/Host.h index 41f4d1e72..4cfca7718 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -95,6 +95,8 @@ public: /// Default host for current version of client. static std::string pocHost(); + static std::unordered_map const& pocHosts(); + /// Register a peer-capability; all new peer connections will have this capability. template std::shared_ptr registerCapability(T* _t) { _t->m_host = this; std::shared_ptr ret(_t); m_capabilities[std::make_pair(T::staticName(), T::staticVersion())] = ret; return ret; } @@ -227,7 +229,7 @@ private: std::shared_ptr m_nodeTable; ///< Node table (uses kademlia-like discovery). /// Shared storage of Peer objects. Peers are created or destroyed on demand by the Host. Active sessions maintain a shared_ptr to a Peer; - std::map> m_peers; + std::unordered_map> m_peers; /// Peers we try to connect regardless of p2p network. std::set m_requiredPeers; @@ -235,7 +237,7 @@ private: /// The nodes to which we are currently connected. Used by host to service peer requests and keepAlivePeers and for shutdown. (see run()) /// Mutable because we flush zombie entries (null-weakptrs) as regular maintenance from a const method. - mutable std::map> m_sessions; + mutable std::unordered_map> m_sessions; mutable RecursiveMutex x_sessions; std::list> m_connecting; ///< Pending connections. diff --git a/libp2p/Network.cpp b/libp2p/Network.cpp index 847e6a42d..d8ab90a20 100644 --- a/libp2p/Network.cpp +++ b/libp2p/Network.cpp @@ -154,12 +154,12 @@ int Network::tcp4Listen(bi::tcp::acceptor& _acceptor, NetworkPreferences const& _acceptor.bind(endpoint); _acceptor.listen(); retport = _acceptor.local_endpoint().port(); + assert(retport == _netPrefs.listenPort); } catch (...) { clog(NetWarn) << "Couldn't start accepting connections on host. Failed to accept socket.\n" << boost::current_exception_diagnostic_information(); } - assert(retport == _netPrefs.listenPort); return retport; } return retport; diff --git a/libp2p/NodeTable.cpp b/libp2p/NodeTable.cpp index 42f1cad02..35cfda64b 100644 --- a/libp2p/NodeTable.cpp +++ b/libp2p/NodeTable.cpp @@ -75,30 +75,20 @@ void NodeTable::processEvents() m_nodeEventHandler->processEvents(); } -shared_ptr NodeTable::addNode(Public const& _pubk, NodeIPEndpoint const& _ep) -{ - auto node = Node(_pubk, _ep); - return addNode(node); -} - shared_ptr NodeTable::addNode(Node const& _node, NodeRelation _relation) { if (_relation == Known) { shared_ptr ret(new NodeEntry(m_node, _node.id, _node.endpoint)); ret->pending = false; - m_nodes[_node.id] = ret; + DEV_GUARDED(x_nodes) + m_nodes[_node.id] = ret; noteActiveNode(_node.id, _node.endpoint); return ret; } - // re-enable tcp checks when NAT hosts are handled by discover - // we handle when tcp endpoint is 0 below - if (_node.endpoint.address.to_string() == "0.0.0.0") - { - clog(NodeTableWarn) << "addNode Failed. Invalid UDP address" << LogTag::Url << "0.0.0.0" << "for" << _node.id; + if (!_node.endpoint) return move(shared_ptr()); - } // ping address to recover nodeid if nodeid is empty if (!_node.id) @@ -108,24 +98,19 @@ shared_ptr NodeTable::addNode(Node const& _node, NodeRelation _relati Guard l(x_pubkDiscoverPings); m_pubkDiscoverPings[_node.endpoint.address] = std::chrono::steady_clock::now(); } - PingNode p(_node.endpoint, m_node.endpoint.address.to_string(), m_node.endpoint.udpPort); - p.sign(m_secret); - m_socketPointer->send(p); + ping(_node.endpoint); return move(shared_ptr()); } - { - Guard ln(x_nodes); + DEV_GUARDED(x_nodes) if (m_nodes.count(_node.id)) return m_nodes[_node.id]; - } shared_ptr ret(new NodeEntry(m_node, _node.id, _node.endpoint)); - m_nodes[_node.id] = ret; + DEV_GUARDED(x_nodes) + m_nodes[_node.id] = ret; clog(NodeTableConnect) << "addNode pending for" << _node.endpoint; - PingNode p(_node.endpoint, m_node.endpoint.address.to_string(), m_node.endpoint.udpPort); - p.sign(m_secret); - m_socketPointer->send(p); + ping(_node.endpoint); return ret; } @@ -142,19 +127,20 @@ void NodeTable::discover() list NodeTable::nodes() const { list nodes; - Guard l(x_nodes); - for (auto& i: m_nodes) - nodes.push_back(i.second->id); + DEV_GUARDED(x_nodes) + for (auto& i: m_nodes) + nodes.push_back(i.second->id); return move(nodes); } list NodeTable::snapshot() const { list ret; - Guard l(x_state); - for (auto s: m_state) - for (auto n: s.nodes) - ret.push_back(*n.lock()); + DEV_GUARDED(x_state) + for (auto const& s: m_state) + for (auto const& np: s.nodes) + if (auto n = np.lock()) + ret.push_back(*n); return move(ret); } @@ -164,8 +150,7 @@ Node NodeTable::node(NodeId const& _id) if (m_nodes.count(_id)) { auto entry = m_nodes[_id]; - Node n(_id, entry->endpoint, entry->required); - return move(n); + return Node(_id, entry->endpoint, entry->required); } return UnspecifiedNode; } @@ -186,7 +171,7 @@ void NodeTable::discover(NodeId _node, unsigned _round, shared_ptr>()); @@ -199,7 +184,8 @@ void NodeTable::discover(NodeId _node, unsigned _round, shared_ptrendpoint, _node); p.sign(m_secret); - m_findNodeTimeout.push_back(make_pair(r->id, chrono::steady_clock::now())); + DEV_GUARDED(x_findNodeTimeout) + m_findNodeTimeout.push_back(make_pair(r->id, chrono::steady_clock::now())); m_socketPointer->send(p); } @@ -240,7 +226,7 @@ vector> NodeTable::nearestNodeEntries(NodeId _target) while (head != tail && head < s_bins && count < s_bucketSize) { Guard l(x_state); - for (auto n: m_state[head].nodes) + for (auto const& n: m_state[head].nodes) if (auto p = n.lock()) { if (count < s_bucketSize) @@ -250,7 +236,7 @@ vector> NodeTable::nearestNodeEntries(NodeId _target) } if (count < s_bucketSize && tail) - for (auto n: m_state[tail].nodes) + for (auto const& n: m_state[tail].nodes) if (auto p = n.lock()) { if (count < s_bucketSize) @@ -267,7 +253,7 @@ vector> NodeTable::nearestNodeEntries(NodeId _target) while (head < s_bins && count < s_bucketSize) { Guard l(x_state); - for (auto n: m_state[head].nodes) + for (auto const& n: m_state[head].nodes) if (auto p = n.lock()) { if (count < s_bucketSize) @@ -281,7 +267,7 @@ vector> NodeTable::nearestNodeEntries(NodeId _target) while (tail > 0 && count < s_bucketSize) { Guard l(x_state); - for (auto n: m_state[tail].nodes) + for (auto const& n: m_state[tail].nodes) if (auto p = n.lock()) { if (count < s_bucketSize) @@ -294,15 +280,15 @@ vector> NodeTable::nearestNodeEntries(NodeId _target) vector> ret; for (auto& nodes: found) - for (auto n: nodes.second) - if (n->endpoint.isAllowed()) + for (auto const& n: nodes.second) + if (ret.size() < s_bucketSize && !!n->endpoint && n->endpoint.isAllowed()) ret.push_back(n); return move(ret); } -void NodeTable::ping(bi::udp::endpoint _to) const +void NodeTable::ping(NodeIPEndpoint _to) const { - PingNode p(_to, m_node.endpoint.address.to_string(), m_node.endpoint.udpPort); + PingNode p(m_node.endpoint, _to); p.sign(m_secret); m_socketPointer->send(p); } @@ -318,12 +304,15 @@ void NodeTable::evict(shared_ptr _leastSeen, shared_ptr _n if (!m_socketPointer->isOpen()) return; + unsigned ec; + DEV_GUARDED(x_evictions) { - Guard l(x_evictions); m_evictions.push_back(EvictionTimeout(make_pair(_leastSeen->id,chrono::steady_clock::now()), _new->id)); - if (m_evictions.size() == 1) - doCheckEvictions(boost::system::error_code()); + ec = m_evictions.size(); } + + if (ec == 1) + doCheckEvictions(boost::system::error_code()); ping(_leastSeen.get()); } @@ -440,39 +429,47 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes Pong in = Pong::fromBytesConstRef(_from, rlpBytes); // whenever a pong is received, check if it's in m_evictions - Guard le(x_evictions); - bool evictionEntry = false; - for (auto it = m_evictions.begin(); it != m_evictions.end(); it++) - if (it->first.first == nodeid && it->first.second > std::chrono::steady_clock::now()) - { - evictionEntry = true; - if (auto n = nodeEntry(it->second)) - dropNode(n); - - if (auto n = nodeEntry(it->first.first)) - n->pending = false; - - it = m_evictions.erase(it); - } - - // if not, check if it's known/pending or a pubk discovery ping - if (!evictionEntry) + bool found = false; + EvictionTimeout evictionEntry; + DEV_GUARDED(x_evictions) + for (auto it = m_evictions.begin(); it != m_evictions.end(); ++it) + if (it->first.first == nodeid && it->first.second > std::chrono::steady_clock::now()) + { + found = true; + evictionEntry = *it; + m_evictions.erase(it); + break; + } + if (found) + { + if (auto n = nodeEntry(evictionEntry.second)) + dropNode(n); + if (auto n = nodeEntry(evictionEntry.first.first)) + n->pending = false; + } + else { + // if not, check if it's known/pending or a pubk discovery ping if (auto n = nodeEntry(nodeid)) n->pending = false; - else if (m_pubkDiscoverPings.count(_from.address())) + else { + DEV_GUARDED(x_pubkDiscoverPings) { - Guard l(x_pubkDiscoverPings); + if (!m_pubkDiscoverPings.count(_from.address())) + return; // unsolicited pong; don't note node as active m_pubkDiscoverPings.erase(_from.address()); } if (!haveNode(nodeid)) - addNode(nodeid, NodeIPEndpoint(_from.address(), _from.port(), _from.port())); + addNode(Node(nodeid, NodeIPEndpoint(_from.address(), _from.port(), _from.port()))); } - else - return; // unsolicited pong; don't note node as active } + // update our endpoint address and UDP port + if ((!m_node.endpoint || !m_node.endpoint.isAllowed()) && isPublicAddress(in.destination.address)) + m_node.endpoint.address = in.destination.address; + m_node.endpoint.udpPort = in.destination.udpPort; + clog(NodeTableConnect) << "PONG from " << nodeid << _from; break; } @@ -481,14 +478,15 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes { bool expected = false; auto now = chrono::steady_clock::now(); - m_findNodeTimeout.remove_if([&](NodeIdTimePoint const& t) - { - if (t.first == nodeid && now - t.second < c_reqTimeout) - expected = true; - else if (t.first == nodeid) - return true; - return false; - }); + DEV_GUARDED(x_findNodeTimeout) + m_findNodeTimeout.remove_if([&](NodeIdTimePoint const& t) + { + if (t.first == nodeid && now - t.second < c_reqTimeout) + expected = true; + else if (t.first == nodeid) + return true; + return false; + }); if (!expected) { @@ -497,17 +495,22 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes } Neighbours in = Neighbours::fromBytesConstRef(_from, rlpBytes); - for (auto n: in.nodes) - addNode(n.node, NodeIPEndpoint(bi::address::from_string(n.ipAddress), n.udpPort, n.udpPort)); + for (auto n: in.neighbours) + addNode(Node(n.node, n.endpoint)); break; } case FindNode::type: { FindNode in = FindNode::fromBytesConstRef(_from, rlpBytes); + if (RLPXDatagramFace::secondsSinceEpoch() > in.ts) + { + clog(NodeTableTriviaSummary) << "Received expired FindNode from " << _from.address().to_string() << ":" << _from.port(); + return; + } vector> nearest = nearestNodeEntries(in.target); - static unsigned const nlimit = (m_socketPointer->maxDatagramSize - 111) / 87; + static unsigned const nlimit = (m_socketPointer->maxDatagramSize - 109) / 90; for (unsigned offset = 0; offset < nearest.size(); offset += nlimit) { Neighbours out(_from, nearest, offset, nlimit); @@ -522,17 +525,29 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes case PingNode::type: { PingNode in = PingNode::fromBytesConstRef(_from, rlpBytes); - if (in.version != dev::p2p::c_protocolVersion) + if (in.version < dev::p2p::c_protocolVersion) { - if (auto n = nodeEntry(nodeid)) - dropNode(n); - return; + if (in.version == 3) + { + compat::Pong p(in.source); + p.echo = sha3(rlpBytes); + p.sign(m_secret); + m_socketPointer->send(p); + } + else + return; } - // TODO: Feedback if _from.address() != in.ipAddress - addNode(nodeid, NodeIPEndpoint(_from.address(), _from.port(), in.tcpPort)); + if (RLPXDatagramFace::secondsSinceEpoch() > in.ts) + { + clog(NodeTableTriviaSummary) << "Received expired PingNode from " << _from.address().to_string() << ":" << _from.port(); + return; + } - Pong p(_from); + in.source.address = _from.address(); + in.source.udpPort = _from.port(); + addNode(Node(nodeid, in.source)); + Pong p(in.source); p.echo = sha3(rlpBytes); p.sign(m_secret); m_socketPointer->send(p); @@ -567,13 +582,13 @@ void NodeTable::doCheckEvictions(boost::system::error_code const& _ec) bool evictionsRemain = false; list> drop; { - Guard ln(x_nodes); Guard le(x_evictions); + Guard ln(x_nodes); for (auto& e: m_evictions) if (chrono::steady_clock::now() - e.first.second > c_reqTimeout) if (m_nodes.count(e.second)) drop.push_back(m_nodes[e.second]); - evictionsRemain = m_evictions.size() - drop.size() > 0; + evictionsRemain = (m_evictions.size() - drop.size() > 0); } drop.unique(); @@ -608,26 +623,44 @@ void NodeTable::doRefreshBuckets(boost::system::error_code const& _ec) void PingNode::streamRLP(RLPStream& _s) const { _s.appendList(4); - _s << dev::p2p::c_protocolVersion << ipAddress << tcpPort << ts; + _s << dev::p2p::c_protocolVersion; + source.streamRLP(_s); + destination.streamRLP(_s); + _s << ts; } void PingNode::interpretRLP(bytesConstRef _bytes) { RLP r(_bytes); - if (r.itemCountStrict() == 3) + if (r.itemCountStrict() == 4 && r[0].isInt() && r[0].toInt(RLP::Strict) == dev::p2p::c_protocolVersion) { - version = 2; - ipAddress = r[0].toString(); - tcpPort = r[1].toInt(RLP::Strict); - ts = r[2].toInt(RLP::Strict); - } - else if (r.itemCountStrict() == 4) - { - version = r[0].toInt(RLP::Strict); - ipAddress = r[1].toString(); - tcpPort = r[2].toInt(RLP::Strict); - ts = r[3].toInt(RLP::Strict); + version = dev::p2p::c_protocolVersion; + source.interpretRLP(r[1]); + destination.interpretRLP(r[2]); + ts = r[3].toInt(RLP::Strict); } else - BOOST_THROW_EXCEPTION(InvalidRLP()); + version = r[0].toInt(RLP::Strict); +} + +void Pong::streamRLP(RLPStream& _s) const +{ + _s.appendList(3); + destination.streamRLP(_s); + _s << echo << ts; +} + +void Pong::interpretRLP(bytesConstRef _bytes) +{ + RLP r(_bytes); + destination.interpretRLP(r[0]); + echo = (h256)r[1]; + ts = r[2].toInt(); +} + +void compat::Pong::interpretRLP(bytesConstRef _bytes) +{ + RLP r(_bytes); + echo = (h256)r[0]; + ts = r[1].toInt(); } diff --git a/libp2p/NodeTable.h b/libp2p/NodeTable.h index 95028db2b..2e10dd891 100644 --- a/libp2p/NodeTable.h +++ b/libp2p/NodeTable.h @@ -45,10 +45,12 @@ struct NodeEntry: public Node bool pending = true; ///< Node will be ignored until Pong is received }; -enum NodeTableEventType { +enum NodeTableEventType +{ NodeEntryAdded, NodeEntryDropped }; + class NodeTable; class NodeTableEventHandler { @@ -80,7 +82,7 @@ protected: Mutex x_events; std::list m_nodeEventHandler; - std::map m_events; + std::unordered_map m_events; }; class NodeTable; @@ -100,23 +102,15 @@ inline std::ostream& operator<<(std::ostream& _out, NodeTable const& _nodeTable) * NodeTable accepts a port for UDP and will listen to the port on all available * interfaces. * - * - * [Integration] - * @todo TCP endpoints - * @todo GC uniform 1/32 entires at 112500ms interval - * * [Optimization] * @todo serialize evictions per-bucket * @todo store evictions in map, unit-test eviction logic * @todo store root node in table * @todo encapsulate discover into NetworkAlgorithm (task) - * @todo Pong to include ip:port where ping was received * @todo expiration and sha3(id) 'to' for messages which are replies (prevents replay) * @todo cache Ping and FindSelf * * [Networking] - * @todo node-endpoint updates - * @todo TCP endpoints * @todo eth/upnp/natpmp/stun/ice/etc for public-discovery * @todo firewall * @@ -131,7 +125,7 @@ class NodeTable: UDPSocketEvents, public std::enable_shared_from_this using TimePoint = std::chrono::steady_clock::time_point; ///< Steady time point. using NodeIdTimePoint = std::pair; using EvictionTimeout = std::pair; ///< First NodeId (NodeIdTimePoint) may be evicted and replaced with second NodeId. - + public: enum NodeRelation { Unknown = 0, Known }; @@ -148,9 +142,6 @@ public: /// Called by implementation which provided handler to process NodeEntryAdded/NodeEntryDropped events. Events are coalesced by type whereby old events are ignored. void processEvents(); - /// Add node. Node will be pinged and empty shared_ptr is returned if NodeId is uknown. - std::shared_ptr addNode(Public const& _pubk, NodeIPEndpoint const& _ep); - /// Add node. Node will be pinged and empty shared_ptr is returned if node has never been seen or NodeId is empty. std::shared_ptr addNode(Node const& _node, NodeRelation _relation = NodeRelation::Unknown); @@ -206,7 +197,7 @@ private: }; /// Used to ping endpoint. - void ping(bi::udp::endpoint _to) const; + void ping(NodeIPEndpoint _to) const; /// Used ping known node. Used by node table when refreshing buckets and as part of eviction process (see evict). void ping(NodeEntry* _n) const; @@ -254,32 +245,32 @@ private: /// Purges and pings nodes for any buckets which haven't been touched for c_bucketRefresh seconds. void doRefreshBuckets(boost::system::error_code const& _ec); - std::unique_ptr m_nodeEventHandler; ///< Event handler for node events. + std::unique_ptr m_nodeEventHandler; ///< Event handler for node events. - Node m_node; ///< This node. - Secret m_secret; ///< This nodes secret key. + Node m_node; ///< This node. + Secret m_secret; ///< This nodes secret key. - mutable Mutex x_nodes; ///< LOCK x_state first if both locks are required. Mutable for thread-safe copy in nodes() const. - std::map> m_nodes; ///< Nodes + mutable Mutex x_nodes; ///< LOCK x_state first if both locks are required. Mutable for thread-safe copy in nodes() const. + std::unordered_map> m_nodes; ///< Nodes - mutable Mutex x_state; ///< LOCK x_state first if both x_nodes and x_state locks are required. - std::array m_state; ///< State of p2p node network. + mutable Mutex x_state; ///< LOCK x_state first if both x_nodes and x_state locks are required. + std::array m_state; ///< State of p2p node network. - Mutex x_evictions; ///< LOCK x_nodes first if both x_nodes and x_evictions locks are required. - std::deque m_evictions; ///< Eviction timeouts. + Mutex x_evictions; ///< LOCK x_evictions first if both x_nodes and x_evictions locks are required. + std::deque m_evictions; ///< Eviction timeouts. - Mutex x_pubkDiscoverPings; ///< LOCK x_nodes first if both x_nodes and x_pubkDiscoverPings locks are required. - std::map m_pubkDiscoverPings; ///< List of pending pings where node entry wasn't created due to unkown pubk. + Mutex x_pubkDiscoverPings; ///< LOCK x_nodes first if both x_nodes and x_pubkDiscoverPings locks are required. + std::unordered_map m_pubkDiscoverPings; ///< List of pending pings where node entry wasn't created due to unkown pubk. Mutex x_findNodeTimeout; - std::list m_findNodeTimeout; ///< Timeouts for pending Ping and FindNode requests. + std::list m_findNodeTimeout; ///< Timeouts for pending Ping and FindNode requests. - ba::io_service& m_io; ///< Used by bucket refresh timer. - std::shared_ptr m_socket; ///< Shared pointer for our UDPSocket; ASIO requires shared_ptr. - NodeSocket* m_socketPointer; ///< Set to m_socket.get(). Socket is created in constructor and disconnected in destructor to ensure access to pointer is safe. + ba::io_service& m_io; ///< Used by bucket refresh timer. + std::shared_ptr m_socket; ///< Shared pointer for our UDPSocket; ASIO requires shared_ptr. + NodeSocket* m_socketPointer; ///< Set to m_socket.get(). Socket is created in constructor and disconnected in destructor to ensure access to pointer is safe. - boost::asio::deadline_timer m_bucketRefreshTimer; ///< Timer which schedules and enacts bucket refresh. - boost::asio::deadline_timer m_evictionCheckTimer; ///< Timer for handling node evictions. + boost::asio::deadline_timer m_bucketRefreshTimer; ///< Timer which schedules and enacts bucket refresh. + boost::asio::deadline_timer m_evictionCheckTimer; ///< Timer for handling node evictions. }; inline std::ostream& operator<<(std::ostream& _out, NodeTable const& _nodeTable) @@ -301,30 +292,21 @@ struct InvalidRLP: public Exception {}; * a given bucket which is full, the least-responsive node is pinged. * If the pinged node doesn't respond, then it is removed and the new * node is inserted. - * - * RLP Encoded Items: 3 - * Minimum Encoded Size: 18 bytes - * Maximum Encoded Size: bytes // todo after u128 addresses - * - * signature: Signature of message. - * ipAddress: Our IP address. - * port: Our port. - * - * @todo uint128_t for ip address (<->integer ipv4/6, asio-address, asio-endpoint) - * */ struct PingNode: RLPXDatagram { - PingNode(bi::udp::endpoint _ep): RLPXDatagram(_ep) {} - PingNode(bi::udp::endpoint _ep, std::string _src, uint16_t _srcPort, std::chrono::seconds _ts = std::chrono::seconds(60)): RLPXDatagram(_ep), ipAddress(_src), tcpPort(_srcPort), ts(futureFromEpoch(_ts)) {} + /// Constructor used for sending PingNode. + PingNode(NodeIPEndpoint _src, NodeIPEndpoint _dest): RLPXDatagram(_dest), source(_src), destination(_dest), ts(futureFromEpoch(std::chrono::seconds(60))) {} + + /// Constructor used to create empty PingNode for parsing inbound packets. + PingNode(bi::udp::endpoint _ep): RLPXDatagram(_ep), source(UnspecifiedNodeIPEndpoint), destination(UnspecifiedNodeIPEndpoint) {} static const uint8_t type = 1; unsigned version = 0; - std::string ipAddress; -// uint16_t udpPort; - uint16_t tcpPort; - unsigned ts; + NodeIPEndpoint source; + NodeIPEndpoint destination; + uint32_t ts = 0; void streamRLP(RLPStream& _s) const override; void interpretRLP(bytesConstRef _bytes) override; @@ -332,22 +314,20 @@ struct PingNode: RLPXDatagram /** * Pong packet: Sent in response to ping - * - * RLP Encoded Items: 2 - * Minimum Encoded Size: 33 bytes - * Maximum Encoded Size: 33 bytes */ struct Pong: RLPXDatagram { - Pong(bi::udp::endpoint _ep): RLPXDatagram(_ep), ts(futureFromEpoch(std::chrono::seconds(60))) {} + Pong(bi::udp::endpoint const& _ep): RLPXDatagram(_ep), destination(UnspecifiedNodeIPEndpoint) {} + Pong(NodeIPEndpoint const& _dest): RLPXDatagram((bi::udp::endpoint)_dest), destination(_dest), ts(futureFromEpoch(std::chrono::seconds(60))) {} static const uint8_t type = 2; + NodeIPEndpoint destination; h256 echo; ///< MCD of PingNode - unsigned ts; + uint32_t ts = 0; - void streamRLP(RLPStream& _s) const { _s.appendList(2); _s << echo << ts; } - void interpretRLP(bytesConstRef _bytes) { RLP r(_bytes); echo = (h256)r[0]; ts = r[1].toInt(); } + void streamRLP(RLPStream& _s) const; + void interpretRLP(bytesConstRef _bytes); }; /** @@ -365,58 +345,63 @@ struct Pong: RLPXDatagram struct FindNode: RLPXDatagram { FindNode(bi::udp::endpoint _ep): RLPXDatagram(_ep) {} - FindNode(bi::udp::endpoint _ep, NodeId _target, std::chrono::seconds _ts = std::chrono::seconds(60)): RLPXDatagram(_ep), target(_target), ts(futureFromEpoch(_ts)) {} + FindNode(bi::udp::endpoint _ep, NodeId _target): RLPXDatagram(_ep), target(_target), ts(futureFromEpoch(std::chrono::seconds(60))) {} static const uint8_t type = 3; h512 target; - unsigned ts; + uint32_t ts = 0; void streamRLP(RLPStream& _s) const { _s.appendList(2); _s << target << ts; } - void interpretRLP(bytesConstRef _bytes) { RLP r(_bytes); target = r[0].toHash(); ts = r[1].toInt(); } + void interpretRLP(bytesConstRef _bytes) { RLP r(_bytes); target = r[0].toHash(); ts = r[1].toInt(); } }; /** - * Node Packet: Multiple node packets are sent in response to FindNode. - * - * RLP Encoded Items: 2 (first item is list) - * Minimum Encoded Size: 10 bytes + * Node Packet: One or more node packets are sent in response to FindNode. */ struct Neighbours: RLPXDatagram { - struct Node + struct Neighbour { - Node() = default; - Node(RLP const& _r) { interpretRLP(_r); } - std::string ipAddress; - uint16_t udpPort; -// uint16_t tcpPort; + Neighbour(Node const& _node): endpoint(_node.endpoint), node(_node.id) {} + Neighbour(RLP const& _r): endpoint(_r) { node = h512(_r[3].toBytes()); } + NodeIPEndpoint endpoint; NodeId node; - void streamRLP(RLPStream& _s) const { _s.appendList(3); _s << ipAddress << udpPort << node; } - void interpretRLP(RLP const& _r) { ipAddress = _r[0].toString(); udpPort = _r[1].toInt(); node = h512(_r[2].toBytes()); } + void streamRLP(RLPStream& _s) const { _s.appendList(4); endpoint.streamRLP(_s, NodeIPEndpoint::StreamInline); _s << node; } }; - Neighbours(bi::udp::endpoint _ep): RLPXDatagram(_ep), ts(futureFromEpoch(std::chrono::seconds(30))) {} - Neighbours(bi::udp::endpoint _to, std::vector> const& _nearest, unsigned _offset = 0, unsigned _limit = 0): RLPXDatagram(_to), ts(futureFromEpoch(std::chrono::seconds(30))) + Neighbours(bi::udp::endpoint _ep): RLPXDatagram(_ep), ts(secondsSinceEpoch()) {} + Neighbours(bi::udp::endpoint _to, std::vector> const& _nearest, unsigned _offset = 0, unsigned _limit = 0): RLPXDatagram(_to), ts(futureFromEpoch(std::chrono::seconds(60))) { auto limit = _limit ? std::min(_nearest.size(), (size_t)(_offset + _limit)) : _nearest.size(); for (auto i = _offset; i < limit; i++) - { - Node node; - node.ipAddress = _nearest[i]->endpoint.address.to_string(); - node.udpPort = _nearest[i]->endpoint.udpPort; - node.node = _nearest[i]->publicKey(); - nodes.push_back(node); - } + neighbours.push_back(Neighbour(*_nearest[i])); } static const uint8_t type = 4; - std::vector nodes; - unsigned ts = 1; + std::vector neighbours; + uint32_t ts = 0; - void streamRLP(RLPStream& _s) const { _s.appendList(2); _s.appendList(nodes.size()); for (auto& n: nodes) n.streamRLP(_s); _s << ts; } - void interpretRLP(bytesConstRef _bytes) { RLP r(_bytes); for (auto n: r[0]) nodes.push_back(Node(n)); ts = r[1].toInt(); } + void streamRLP(RLPStream& _s) const { _s.appendList(2); _s.appendList(neighbours.size()); for (auto& n: neighbours) n.streamRLP(_s); _s << ts; } + void interpretRLP(bytesConstRef _bytes) { RLP r(_bytes); for (auto n: r[0]) neighbours.push_back(Neighbour(n)); ts = r[1].toInt(); } }; + +namespace compat +{ + /** + * Pong packet [compatability]: Sent in response to ping + */ + struct Pong: RLPXDatagram + { + Pong(bi::udp::endpoint const& _ep): RLPXDatagram(_ep) {} + Pong(NodeIPEndpoint const& _dest): RLPXDatagram((bi::udp::endpoint)_dest), ts(futureFromEpoch(std::chrono::seconds(60))) {} + static const uint8_t type = 2; + h256 echo; + uint32_t ts = 0; + void streamRLP(RLPStream& _s) const { _s.appendList(2); _s << echo << ts; } + void interpretRLP(bytesConstRef _bytes); + }; +} struct NodeTableWarn: public LogChannel { static const char* name(); static const int verbosity = 0; }; struct NodeTableNote: public LogChannel { static const char* name(); static const int verbosity = 1; }; diff --git a/libp2p/UDP.cpp b/libp2p/UDP.cpp index eeb3a0b1a..9f89d9ad0 100644 --- a/libp2p/UDP.cpp +++ b/libp2p/UDP.cpp @@ -20,9 +20,13 @@ */ #include "UDP.h" +using namespace std; using namespace dev; using namespace dev::p2p; +const char* RLPXWarn::name() { return "!X!"; } +const char* RLPXNote::name() { return "-X-"; } + h256 RLPXDatagramFace::sign(Secret const& _k) { assert(packetType()); diff --git a/libp2p/UDP.h b/libp2p/UDP.h index 374f986b0..b09d556e7 100644 --- a/libp2p/UDP.h +++ b/libp2p/UDP.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "Common.h" namespace ba = boost::asio; @@ -40,6 +41,9 @@ namespace dev namespace p2p { +struct RLPXWarn: public LogChannel { static const char* name(); static const int verbosity = 0; }; +struct RLPXNote: public LogChannel { static const char* name(); static const int verbosity = 1; }; + /** * UDP Datagram * @todo make data protected/functional @@ -61,8 +65,8 @@ protected: */ struct RLPXDatagramFace: public UDPDatagram { - static uint64_t futureFromEpoch(std::chrono::milliseconds _ms) { return std::chrono::duration_cast((std::chrono::system_clock::now() + _ms).time_since_epoch()).count(); } - static uint64_t futureFromEpoch(std::chrono::seconds _sec) { return std::chrono::duration_cast((std::chrono::system_clock::now() + _sec).time_since_epoch()).count(); } + static uint32_t futureFromEpoch(std::chrono::seconds _sec) { return std::chrono::duration_cast((std::chrono::system_clock::now() + _sec).time_since_epoch()).count(); } + static uint32_t secondsSinceEpoch() { return std::chrono::duration_cast((std::chrono::system_clock::now()).time_since_epoch()).count(); } static Public authenticate(bytesConstRef _sig, bytesConstRef _rlp); virtual uint8_t packetType() = 0; @@ -203,14 +207,14 @@ void UDPSocket::doRead() auto self(UDPSocket::shared_from_this()); m_socket.async_receive_from(boost::asio::buffer(m_recvData), m_recvEndpoint, [this, self](boost::system::error_code _ec, size_t _len) { - // ASIO Safety: It is possible that ASIO will call lambda w/o an error - // and after the socket has been disconnected. Checking m_closed - // guarantees that m_host will not be called after disconnect(). - if (_ec || m_closed) + if (m_closed) return disconnectWithError(_ec); + + if (_ec != boost::system::errc::success) + clog(NetWarn) << "Receiving UDP message failed. " << _ec.value() << ":" << _ec.message(); - assert(_len); - m_host.onReceived(this, m_recvEndpoint, bytesConstRef(m_recvData.data(), _len)); + if (_len) + m_host.onReceived(this, m_recvEndpoint, bytesConstRef(m_recvData.data(), _len)); doRead(); }); } @@ -223,17 +227,19 @@ void UDPSocket::doWrite() const UDPDatagram& datagram = m_sendQ[0]; auto self(UDPSocket::shared_from_this()); - m_socket.async_send_to(boost::asio::buffer(datagram.data), datagram.endpoint(), [this, self](boost::system::error_code _ec, std::size_t) + bi::udp::endpoint endpoint(datagram.endpoint()); + m_socket.async_send_to(boost::asio::buffer(datagram.data), endpoint, [this, self, endpoint](boost::system::error_code _ec, std::size_t) { - if (_ec || m_closed) + if (m_closed) return disconnectWithError(_ec); - else - { - Guard l(x_sendQ); - m_sendQ.pop_front(); - if (m_sendQ.empty()) - return; - } + + if (_ec != boost::system::errc::success) + clog(NetWarn) << "Failed delivering UDP message. " << _ec.value() << ":" << _ec.message(); + + Guard l(x_sendQ); + m_sendQ.pop_front(); + if (m_sendQ.empty()) + return; doWrite(); }); } diff --git a/libsolidity/AST.h b/libsolidity/AST.h index fde0b71b0..be5c9a6cd 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -1220,7 +1220,7 @@ public: /// Stores a set of possible declarations referenced by this identifier. Has to be resolved /// providing argument types using overloadResolution before the referenced declaration /// is accessed. - void setOverloadedDeclarations(std::set const& _declarations) + void setOverloadedDeclarations(std::vector const& _declarations) { m_overloadedDeclarations = _declarations; } @@ -1237,8 +1237,8 @@ private: /// Stores a reference to the current contract. This is needed because types of base contracts /// change depending on the context. ContractDefinition const* m_currentContract = nullptr; - /// A set of overloaded declarations, right now only FunctionDefinition has overloaded declarations. - std::set m_overloadedDeclarations; + /// A vector of overloaded declarations, right now only FunctionDefinition has overloaded declarations. + std::vector m_overloadedDeclarations; }; /** diff --git a/libsolidity/ASTPrinter.h b/libsolidity/ASTPrinter.h index dabf6470a..25678c176 100644 --- a/libsolidity/ASTPrinter.h +++ b/libsolidity/ASTPrinter.h @@ -42,7 +42,7 @@ public: ASTPrinter( ASTNode const& _ast, std::string const& _source = std::string(), - StructuralGasEstimator::ASTGasConsumption const& _gasCosts = {} + StructuralGasEstimator::ASTGasConsumption const& _gasCosts = StructuralGasEstimator::ASTGasConsumption() ); /// Output the string representation of the AST to _stream. void print(std::ostream& _stream); diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index fb2ab3156..bcd4f9d68 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -206,16 +206,9 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract) void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool _fromMemory) { - // We do not check the calldata size, everything is zero-padded. - unsigned offset(CompilerUtils::dataStartOffset); + // We do not check the calldata size, everything is zero-paddedd - bigint parameterHeadEnd = offset; - for (TypePointer const& type: _typeParameters) - parameterHeadEnd += type->isDynamicallySized() ? 32 : type->getCalldataEncodedSize(); - solAssert(parameterHeadEnd <= numeric_limits::max(), "Arguments too large."); - - unsigned stackHeightOfPreviousDynamicArgument = 0; - ArrayType const* previousDynamicType = nullptr; + m_context << u256(CompilerUtils::dataStartOffset); for (TypePointer const& type: _typeParameters) { switch (type->getCategory()) @@ -223,34 +216,31 @@ void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool case Type::Category::Array: if (type->isDynamicallySized()) { - // put on stack: data_offset length - unsigned newStackHeight = m_context.getStackHeight(); - if (previousDynamicType) - { - // Retrieve data start offset by adding length to start offset of previous dynamic type - unsigned stackDepth = m_context.getStackHeight() - stackHeightOfPreviousDynamicArgument; - solAssert(stackDepth <= 16, "Stack too deep."); - m_context << eth::dupInstruction(stackDepth) << eth::dupInstruction(stackDepth); - ArrayUtils(m_context).convertLengthToSize(*previousDynamicType, true); - m_context << eth::Instruction::ADD; - } - else - m_context << u256(parameterHeadEnd); - stackHeightOfPreviousDynamicArgument = newStackHeight; - previousDynamicType = &dynamic_cast(*type); - offset += CompilerUtils(m_context).loadFromMemory(offset, IntegerType(256), !_fromMemory); + // put on stack: data_pointer length + CompilerUtils(m_context).loadFromMemoryDynamic(IntegerType(256), !_fromMemory); + // stack: data_offset next_pointer + //@todo once we support nested arrays, this offset needs to be dynamic. + m_context << eth::Instruction::SWAP1 << u256(CompilerUtils::dataStartOffset); + m_context << eth::Instruction::ADD; + // stack: next_pointer data_pointer + // retrieve length + CompilerUtils(m_context).loadFromMemoryDynamic(IntegerType(256), !_fromMemory, true); + // stack: next_pointer length data_pointer + m_context << eth::Instruction::SWAP2; } else { - m_context << u256(offset); - offset += type->getCalldataEncodedSize(); + // leave the pointer on the stack + m_context << eth::Instruction::DUP1; + m_context << u256(type->getCalldataEncodedSize()) << eth::Instruction::ADD; } break; default: solAssert(!type->isDynamicallySized(), "Unknown dynamically sized type: " + type->toString()); - offset += CompilerUtils(m_context).loadFromMemory(offset, *type, !_fromMemory, true); + CompilerUtils(m_context).loadFromMemoryDynamic(*type, !_fromMemory, true); } } + m_context << eth::Instruction::POP; } void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters) diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp index 554d06fd7..b3fedc45d 100644 --- a/libsolidity/CompilerStack.cpp +++ b/libsolidity/CompilerStack.cpp @@ -257,6 +257,18 @@ bytes CompilerStack::staticCompile(std::string const& _sourceCode, bool _optimiz return stack.compile(_sourceCode, _optimize); } +tuple CompilerStack::positionFromSourceLocation(SourceLocation const& _sourceLocation) const +{ + int startLine; + int startColumn; + int endLine; + int endColumn; + tie(startLine, startColumn) = getScanner(*_sourceLocation.sourceName).translatePositionToLineColumn(_sourceLocation.start); + tie(endLine, endColumn) = getScanner(*_sourceLocation.sourceName).translatePositionToLineColumn(_sourceLocation.end); + + return make_tuple(++startLine, ++startColumn, ++endLine, ++endColumn); +} + void CompilerStack::reset(bool _keepSources) { m_parseSuccessful = false; diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h index 7d9198622..2ad791f22 100644 --- a/libsolidity/CompilerStack.h +++ b/libsolidity/CompilerStack.h @@ -31,6 +31,7 @@ #include #include #include +#include namespace dev { @@ -131,6 +132,11 @@ public: /// scanning the source code - this is useful for printing exception information. static bytes staticCompile(std::string const& _sourceCode, bool _optimize = false); + /// Helper function for logs printing. Do only use in error cases, it's quite expensive. + /// line and columns are numbered starting from 1 with following order: + /// start line, start column, end line, end column + std::tuple positionFromSourceLocation(SourceLocation const& _sourceLocation) const; + private: /** * Information pertaining to one source unit, filled gradually during parsing and compilation. diff --git a/libsolidity/DeclarationContainer.cpp b/libsolidity/DeclarationContainer.cpp index c836663c7..3e23d93b8 100644 --- a/libsolidity/DeclarationContainer.cpp +++ b/libsolidity/DeclarationContainer.cpp @@ -37,6 +37,7 @@ Declaration const* DeclarationContainer::conflictingDeclaration(Declaration cons declarations += m_declarations.at(name); if (m_invisibleDeclarations.count(name)) declarations += m_invisibleDeclarations.at(name); + if (dynamic_cast(&_declaration)) { // check that all other declarations with the same name are functions @@ -66,14 +67,13 @@ bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, return false; if (_invisible) - m_invisibleDeclarations[name].insert(&_declaration); + m_invisibleDeclarations[name].push_back(&_declaration); else - m_declarations[name].insert(&_declaration); - + m_declarations[name].push_back(&_declaration); return true; } -set DeclarationContainer::resolveName(ASTString const& _name, bool _recursive) const +std::vector DeclarationContainer::resolveName(ASTString const& _name, bool _recursive) const { solAssert(!_name.empty(), "Attempt to resolve empty name."); auto result = m_declarations.find(_name); @@ -81,5 +81,5 @@ set DeclarationContainer::resolveName(ASTString const& _name return result->second; if (_recursive && m_enclosingContainer) return m_enclosingContainer->resolveName(_name, true); - return set({}); + return vector({}); } diff --git a/libsolidity/DeclarationContainer.h b/libsolidity/DeclarationContainer.h index 94545eefb..0f0b57179 100644 --- a/libsolidity/DeclarationContainer.h +++ b/libsolidity/DeclarationContainer.h @@ -48,17 +48,17 @@ public: /// @param _update if true, replaces a potential declaration that is already present /// @returns false if the name was already declared. bool registerDeclaration(Declaration const& _declaration, bool _invisible = false, bool _update = false); - std::set resolveName(ASTString const& _name, bool _recursive = false) const; + std::vector resolveName(ASTString const& _name, bool _recursive = false) const; Declaration const* getEnclosingDeclaration() const { return m_enclosingDeclaration; } - std::map> const& getDeclarations() const { return m_declarations; } + std::map> const& getDeclarations() const { return m_declarations; } /// @returns whether declaration is valid, and if not also returns previous declaration. Declaration const* conflictingDeclaration(Declaration const& _declaration) const; private: Declaration const* m_enclosingDeclaration; DeclarationContainer const* m_enclosingContainer; - std::map> m_declarations; - std::map> m_invisibleDeclarations; + std::map> m_declarations; + std::map> m_invisibleDeclarations; }; } diff --git a/libsolidity/InterfaceHandler.cpp b/libsolidity/InterfaceHandler.cpp index d4958475b..a49c4dc3f 100644 --- a/libsolidity/InterfaceHandler.cpp +++ b/libsolidity/InterfaceHandler.cpp @@ -55,15 +55,19 @@ std::unique_ptr InterfaceHandler::getABIInterface(ContractDefinitio for (auto it: _contractDef.getInterfaceFunctions()) { - + auto externalFunctionType = it.second->externalFunctionType(); Json::Value method; method["type"] = "function"; method["name"] = it.second->getDeclaration().getName(); method["constant"] = it.second->isConstant(); - method["inputs"] = populateParameters(it.second->getParameterNames(), - it.second->getParameterTypeNames()); - method["outputs"] = populateParameters(it.second->getReturnParameterNames(), - it.second->getReturnParameterTypeNames()); + method["inputs"] = populateParameters( + externalFunctionType->getParameterNames(), + externalFunctionType->getParameterTypeNames() + ); + method["outputs"] = populateParameters( + externalFunctionType->getReturnParameterNames(), + externalFunctionType->getReturnParameterTypeNames() + ); abi.append(method); } if (_contractDef.getConstructor()) diff --git a/libsolidity/NameAndTypeResolver.cpp b/libsolidity/NameAndTypeResolver.cpp index 9aebbf054..5ef14f60b 100644 --- a/libsolidity/NameAndTypeResolver.cpp +++ b/libsolidity/NameAndTypeResolver.cpp @@ -53,9 +53,13 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) m_currentScope = &m_scopes[&_contract]; linearizeBaseContracts(_contract); - // we first import non-functions only as we do not yet know the argument types - for (ContractDefinition const* base: _contract.getLinearizedBaseContracts()) - importInheritedScope(*base, false); // import non-functions + std::vector properBases( + ++_contract.getLinearizedBaseContracts().begin(), + _contract.getLinearizedBaseContracts().end() + ); + + for (ContractDefinition const* base: properBases) + importInheritedScope(*base); for (ASTPointer const& structDef: _contract.getDefinedStructs()) ReferencesResolver resolver(*structDef, *this, &_contract, nullptr); @@ -80,8 +84,6 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) } m_currentScope = &m_scopes[&_contract]; - for (ContractDefinition const* base: _contract.getLinearizedBaseContracts()) - importInheritedScope(*base, true); // import functions // now resolve references inside the code for (ASTPointer const& modifier: _contract.getFunctionModifiers()) @@ -115,20 +117,55 @@ void NameAndTypeResolver::updateDeclaration(Declaration const& _declaration) solAssert(_declaration.getScope() == nullptr, "Updated declaration outside global scope."); } -set NameAndTypeResolver::resolveName(ASTString const& _name, Declaration const* _scope) const +vector NameAndTypeResolver::resolveName(ASTString const& _name, Declaration const* _scope) const { auto iterator = m_scopes.find(_scope); if (iterator == end(m_scopes)) - return set({}); + return vector({}); return iterator->second.resolveName(_name, false); } -set NameAndTypeResolver::getNameFromCurrentScope(ASTString const& _name, bool _recursive) +vector NameAndTypeResolver::getNameFromCurrentScope(ASTString const& _name, bool _recursive) { return m_currentScope->resolveName(_name, _recursive); } -void NameAndTypeResolver::importInheritedScope(ContractDefinition const& _base, bool _importFunctions) +vector NameAndTypeResolver::cleanedDeclarations( + Identifier const& _identifier, + vector const& _declarations +) +{ + solAssert(_declarations.size() > 1, ""); + vector uniqueFunctions; + + for (auto it = _declarations.begin(); it != _declarations.end(); ++it) + { + solAssert(*it, ""); + // the declaration is functionDefinition while declarations > 1 + FunctionDefinition const& functionDefinition = dynamic_cast(**it); + FunctionType functionType(functionDefinition); + for (auto parameter: functionType.getParameterTypes() + functionType.getReturnParameterTypes()) + if (!parameter) + BOOST_THROW_EXCEPTION( + DeclarationError() << + errinfo_sourceLocation(_identifier.getLocation()) << + errinfo_comment("Function type can not be used in this context") + ); + if (uniqueFunctions.end() == find_if( + uniqueFunctions.begin(), + uniqueFunctions.end(), + [&](Declaration const* d) + { + FunctionType newFunctionType(dynamic_cast(*d)); + return functionType.hasEqualArgumentTypes(newFunctionType); + } + )) + uniqueFunctions.push_back(*it); + } + return uniqueFunctions; +} + +void NameAndTypeResolver::importInheritedScope(ContractDefinition const& _base) { auto iterator = m_scopes.find(&_base); solAssert(iterator != end(m_scopes), ""); @@ -136,30 +173,7 @@ void NameAndTypeResolver::importInheritedScope(ContractDefinition const& _base, for (auto const& declaration: nameAndDeclaration.second) // Import if it was declared in the base, is not the constructor and is visible in derived classes if (declaration->getScope() == &_base && declaration->isVisibleInDerivedContracts()) - { - auto function = dynamic_cast(declaration); - if ((function == nullptr) == _importFunctions) - continue; - if (!!function) - { - FunctionType functionType(*function); - // only import if a function with the same arguments does not exist yet - bool functionWithEqualArgumentsFound = false; - for (auto knownDeclaration: m_currentScope->resolveName(nameAndDeclaration.first)) - { - auto knownFunction = dynamic_cast(knownDeclaration); - if (!knownFunction) - continue; // this is not legal, but will be caught later - if (!FunctionType(*knownFunction).hasEqualArgumentTypes(functionType)) - continue; - functionWithEqualArgumentsFound = true; - break; - } - if (functionWithEqualArgumentsFound) - continue; - } m_currentScope->registerDeclaration(*declaration); - } } void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract) const @@ -465,10 +479,9 @@ bool ReferencesResolver::visit(Identifier& _identifier) errinfo_comment("Undeclared identifier.") ); else if (declarations.size() == 1) - _identifier.setReferencedDeclaration(**declarations.begin(), m_currentContract); + _identifier.setReferencedDeclaration(*declarations.front(), m_currentContract); else - // Duplicate declaration will be checked in checkTypeRequirements() - _identifier.setOverloadedDeclarations(declarations); + _identifier.setOverloadedDeclarations(m_resolver.cleanedDeclarations(_identifier, declarations)); return false; } diff --git a/libsolidity/NameAndTypeResolver.h b/libsolidity/NameAndTypeResolver.h index 6528bbef2..d7a0a3b2f 100644 --- a/libsolidity/NameAndTypeResolver.h +++ b/libsolidity/NameAndTypeResolver.h @@ -56,19 +56,24 @@ public: /// Resolves the given @a _name inside the scope @a _scope. If @a _scope is omitted, /// the global scope is used (i.e. the one containing only the contract). /// @returns a pointer to the declaration on success or nullptr on failure. - std::set resolveName(ASTString const& _name, Declaration const* _scope = nullptr) const; + std::vector resolveName(ASTString const& _name, Declaration const* _scope = nullptr) const; /// Resolves a name in the "current" scope. Should only be called during the initial /// resolving phase. - std::set getNameFromCurrentScope(ASTString const& _name, bool _recursive = true); + std::vector getNameFromCurrentScope(ASTString const& _name, bool _recursive = true); + + /// returns the vector of declarations without repetitions + static std::vector cleanedDeclarations( + Identifier const& _identifier, + std::vector const& _declarations + ); private: void reset(); - /// Either imports all non-function members or all function members declared directly in the - /// given contract (i.e. does not import inherited members) into the current scope if they are - ///not present already. - void importInheritedScope(ContractDefinition const& _base, bool _importFunctions); + /// Imports all members declared directly in the given contract (i.e. does not import inherited members) + /// into the current scope if they are not present already. + void importInheritedScope(ContractDefinition const& _base); /// Computes "C3-Linearization" of base contracts and stores it inside the contract. void linearizeBaseContracts(ContractDefinition& _contract) const; diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 65a6867d6..da2fcdb89 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -617,6 +617,7 @@ public: /// @returns true if this function can take the given argument types (possibly /// after implicit conversion). bool canTakeArguments(TypePointers const& _arguments) const; + /// @returns true if the types of parameters are equal (does't check return parameter types) bool hasEqualArgumentTypes(FunctionType const& _other) const; Location const& getLocation() const { return m_location; } diff --git a/libtestutils/FixedWebThreeServer.cpp b/libtestutils/FixedWebThreeServer.cpp index c72a106c6..0be34cc93 100644 --- a/libtestutils/FixedWebThreeServer.cpp +++ b/libtestutils/FixedWebThreeServer.cpp @@ -16,7 +16,12 @@ */ /** @file FixedWebThreeStubServer.cpp * @author Marek Kotewicz + * @author Gav Wood * @date 2015 */ #include "FixedWebThreeServer.h" +#include +using namespace std; +using namespace dev; +using namespace eth; diff --git a/libtestutils/FixedWebThreeServer.h b/libtestutils/FixedWebThreeServer.h index 33ccbf71e..bcaacecd8 100644 --- a/libtestutils/FixedWebThreeServer.h +++ b/libtestutils/FixedWebThreeServer.h @@ -23,6 +23,7 @@ #include #include +#include /** * @brief dummy JSON-RPC api implementation @@ -33,7 +34,10 @@ class FixedWebThreeServer: public dev::WebThreeStubServerBase, public dev::WebThreeStubDatabaseFace { public: - FixedWebThreeServer(jsonrpc::AbstractServerConnector& _conn, std::vector const& _accounts, dev::eth::Interface* _client): WebThreeStubServerBase(_conn, _accounts), m_client(_client) {}; + FixedWebThreeServer(jsonrpc::AbstractServerConnector& _conn, std::vector const& _allAccounts, dev::eth::Interface* _client): + WebThreeStubServerBase(_conn, std::make_shared([=](){return _client;}, _allAccounts), _allAccounts), + m_client(_client) + {} private: dev::eth::Interface* client() override { return m_client; } diff --git a/libweb3jsonrpc/AccountHolder.cpp b/libweb3jsonrpc/AccountHolder.cpp index b88397953..a73f20680 100644 --- a/libweb3jsonrpc/AccountHolder.cpp +++ b/libweb3jsonrpc/AccountHolder.cpp @@ -26,6 +26,7 @@ #include #include #include +#include using namespace std; using namespace dev; @@ -35,31 +36,23 @@ vector g_emptyQueue; static std::mt19937 g_randomNumberGenerator(time(0)); static Mutex x_rngMutex; -void AccountHolder::setAccounts(vector const& _accounts) +vector
AccountHolder::allAccounts() const { - m_accounts.clear(); - for (auto const& keyPair: _accounts) - { - m_accounts.push_back(keyPair.address()); - m_keyPairs[keyPair.address()] = keyPair; - } -} - -vector
AccountHolder::getAllAccounts() const -{ - vector
accounts = m_accounts; + vector
accounts; + accounts += realAccounts(); for (auto const& pair: m_proxyAccounts) if (!isRealAccount(pair.first)) accounts.push_back(pair.first); return accounts; } -Address const& AccountHolder::getDefaultTransactAccount() const +Address const& AccountHolder::defaultTransactAccount() const { - if (m_accounts.empty()) + auto accounts = realAccounts(); + if (accounts.empty()) return ZeroAddress; - Address const* bestMatch = &m_accounts.front(); - for (auto const& account: m_accounts) + Address const* bestMatch = &*accounts.begin(); + for (auto const& account: accounts) if (m_client()->balanceAt(account) > m_client()->balanceAt(*bestMatch)) bestMatch = &account; return *bestMatch; @@ -94,7 +87,7 @@ void AccountHolder::queueTransaction(TransactionSkeleton const& _transaction) m_transactionQueues[id].second.push_back(_transaction); } -vector const& AccountHolder::getQueuedTransactions(int _id) const +vector const& AccountHolder::queuedTransactions(int _id) const { if (!m_transactionQueues.count(_id)) return g_emptyQueue; @@ -106,3 +99,27 @@ void AccountHolder::clearQueue(int _id) if (m_transactionQueues.count(_id)) m_transactionQueues.at(_id).second.clear(); } + +AddressHash SimpleAccountHolder::realAccounts() const +{ + return m_keyManager.accounts(); +} + +void SimpleAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t) +{ + if (isRealAccount(_t.from)) + m_client()->submitTransaction(m_keyManager.secret(_t.from, [&](){ return m_getPassword(_t.from); }), _t); + else if (isProxyAccount(_t.from)) + queueTransaction(_t); +} + +void FixedAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t) +{ + if (isRealAccount(_t.from)) + m_client()->submitTransaction(m_accounts[_t.from], _t); + else if (isProxyAccount(_t.from)) + queueTransaction(_t); +} + + + diff --git a/libweb3jsonrpc/AccountHolder.h b/libweb3jsonrpc/AccountHolder.h index 52005b51f..10b036226 100644 --- a/libweb3jsonrpc/AccountHolder.h +++ b/libweb3jsonrpc/AccountHolder.h @@ -24,17 +24,20 @@ #pragma once #include +#include #include #include #include #include +#include namespace dev { namespace eth { + +class KeyManager; class Interface; -} /** * Manages real accounts (where we know the secret key) and proxy accounts (where transactions @@ -43,32 +46,84 @@ class Interface; class AccountHolder { public: - explicit AccountHolder(std::function const& _client): m_client(_client) {} + explicit AccountHolder(std::function const& _client): m_client(_client) {} + + // easiest to return keyManager.addresses(); + virtual AddressHash realAccounts() const = 0; + // use m_web3's submitTransaction + // or use AccountHolder::queueTransaction(_t) to accept + virtual void authenticate(dev::eth::TransactionSkeleton const& _t) = 0; - /// Sets or resets the list of real accounts. - void setAccounts(std::vector const& _accounts); - std::vector
const& getRealAccounts() const { return m_accounts; } - bool isRealAccount(Address const& _account) const { return m_keyPairs.count(_account) > 0; } + Addresses allAccounts() const; + bool isRealAccount(Address const& _account) const { return realAccounts().count(_account) > 0; } bool isProxyAccount(Address const& _account) const { return m_proxyAccounts.count(_account) > 0; } - Secret const& secretKey(Address const& _account) const { return m_keyPairs.at(_account).secret(); } - std::vector
getAllAccounts() const; - Address const& getDefaultTransactAccount() const; + Address const& defaultTransactAccount() const; int addProxyAccount(Address const& _account); bool removeProxyAccount(unsigned _id); void queueTransaction(eth::TransactionSkeleton const& _transaction); - std::vector const& getQueuedTransactions(int _id) const; + std::vector const& queuedTransactions(int _id) const; void clearQueue(int _id); +protected: + std::function m_client; + private: using TransactionQueue = std::vector; - std::map m_keyPairs; - std::vector
m_accounts; - std::map m_proxyAccounts; - std::map> m_transactionQueues; - std::function m_client; + std::unordered_map m_proxyAccounts; + std::unordered_map> m_transactionQueues; +}; + +class SimpleAccountHolder: public AccountHolder +{ +public: + SimpleAccountHolder(std::function const& _client, std::function const& _getPassword, KeyManager& _keyman): + AccountHolder(_client), + m_getPassword(_getPassword), + m_keyManager(_keyman) + {} + + AddressHash realAccounts() const override; + void authenticate(dev::eth::TransactionSkeleton const& _t) override; + +private: + std::function m_getPassword; + KeyManager& m_keyManager; +}; + +class FixedAccountHolder: public AccountHolder +{ +public: + FixedAccountHolder(std::function const& _client, std::vector const& _accounts): + AccountHolder(_client) + { + setAccounts(_accounts); + } + + void setAccounts(std::vector const& _accounts) + { + for (auto const& i: _accounts) + m_accounts[i.address()] = i.secret(); + } + + dev::AddressHash realAccounts() const override + { + dev::AddressHash ret; + for (auto const& i: m_accounts) + ret.insert(i.first); + return ret; + } + + // use m_web3's submitTransaction + // or use AccountHolder::queueTransaction(_t) to accept + void authenticate(dev::eth::TransactionSkeleton const& _t) override; + +private: + std::unordered_map m_accounts; }; + +} } diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 30a634b3d..5235b0c4f 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -33,8 +33,8 @@ using namespace std; using namespace dev; using namespace dev::eth; -WebThreeStubServer::WebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, WebThreeDirect& _web3, std::vector const& _accounts): - WebThreeStubServerBase(_conn, _accounts), +WebThreeStubServer::WebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, WebThreeDirect& _web3, shared_ptr const& _ethAccounts, std::vector const& _shhAccounts): + WebThreeStubServerBase(_conn, _ethAccounts, _shhAccounts), m_web3(_web3) { auto path = getDataDir() + "/.web3"; diff --git a/libweb3jsonrpc/WebThreeStubServer.h b/libweb3jsonrpc/WebThreeStubServer.h index 08991d2f5..35c35c3f0 100644 --- a/libweb3jsonrpc/WebThreeStubServer.h +++ b/libweb3jsonrpc/WebThreeStubServer.h @@ -41,7 +41,7 @@ class WebThreeDirect; class WebThreeStubServer: public dev::WebThreeStubServerBase, public dev::WebThreeStubDatabaseFace { public: - WebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3, std::vector const& _accounts); + WebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3, std::shared_ptr const& _ethAccounts, std::vector const& _shhAccounts); virtual std::string web3_clientVersion(); diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index b5f212f7d..cac634a61 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -297,17 +297,18 @@ static Json::Value toJson(h256 const& _h, shh::Envelope const& _e, shh::Message return res; } -WebThreeStubServerBase::WebThreeStubServerBase(AbstractServerConnector& _conn, vector const& _accounts): - AbstractWebThreeStubServer(_conn), m_accounts(make_shared(bind(&WebThreeStubServerBase::client, this))) +WebThreeStubServerBase::WebThreeStubServerBase(AbstractServerConnector& _conn, std::shared_ptr const& _ethAccounts, vector const& _sshAccounts): + AbstractWebThreeStubServer(_conn), + m_ethAccounts(_ethAccounts) { - m_accounts->setAccounts(_accounts); + setIdentities(_sshAccounts); } void WebThreeStubServerBase::setIdentities(vector const& _ids) { - m_ids.clear(); + m_shhIds.clear(); for (auto i: _ids) - m_ids[i.pub()] = i.secret(); + m_shhIds[i.pub()] = i.secret(); } string WebThreeStubServerBase::web3_sha3(string const& _param1) @@ -353,7 +354,7 @@ string WebThreeStubServerBase::eth_gasPrice() Json::Value WebThreeStubServerBase::eth_accounts() { Json::Value ret(Json::arrayValue); - for (auto const& i: m_accounts->getAllAccounts()) + for (auto const& i: m_ethAccounts->allAccounts()) ret.append(toJS(i)); return ret; } @@ -499,18 +500,15 @@ string WebThreeStubServerBase::eth_sendTransaction(Json::Value const& _json) TransactionSkeleton t = toTransaction(_json); if (!t.from) - t.from = m_accounts->getDefaultTransactAccount(); + t.from = m_ethAccounts->defaultTransactAccount(); if (t.creation) ret = toJS(right160(sha3(rlpList(t.from, client()->countAt(t.from)))));; - if (!t.gasPrice) + if (t.gasPrice == UndefinedU256) t.gasPrice = 10 * dev::eth::szabo; // TODO: should be determined by user somehow. - if (!t.gas) + if (t.gas == UndefinedU256) t.gas = min(client()->gasLimitRemaining() / 5, client()->balanceAt(t.from) / t.gasPrice); - if (m_accounts->isRealAccount(t.from)) - authenticate(t, false); - else if (m_accounts->isProxyAccount(t.from)) - authenticate(t, true); + m_ethAccounts->authenticate(t); return ret; } @@ -528,18 +526,15 @@ string WebThreeStubServerBase::eth_signTransaction(Json::Value const& _json) TransactionSkeleton t = toTransaction(_json); if (!t.from) - t.from = m_accounts->getDefaultTransactAccount(); + t.from = m_ethAccounts->defaultTransactAccount(); if (t.creation) ret = toJS(right160(sha3(rlpList(t.from, client()->countAt(t.from)))));; - if (!t.gasPrice) + if (t.gasPrice == UndefinedU256) t.gasPrice = 10 * dev::eth::szabo; // TODO: should be determined by user somehow. - if (!t.gas) + if (t.gas == UndefinedU256) t.gas = min(client()->gasLimitRemaining() / 5, client()->balanceAt(t.from) / t.gasPrice); - if (m_accounts->isRealAccount(t.from)) - authenticate(t, false); - else if (m_accounts->isProxyAccount(t.from)) - authenticate(t, true); + m_ethAccounts->authenticate(t); return toJS((t.creation ? Transaction(t.value, t.gasPrice, t.gas, t.data) : Transaction(t.value, t.gasPrice, t.gas, t.to, t.data)).sha3(WithoutSignature)); } @@ -579,21 +574,20 @@ string WebThreeStubServerBase::eth_call(Json::Value const& _json, string const& { TransactionSkeleton t = toTransaction(_json); if (!t.from) - t.from = m_accounts->getDefaultTransactAccount(); + t.from = m_ethAccounts->defaultTransactAccount(); // if (!m_accounts->isRealAccount(t.from)) // return ret; - if (!t.gasPrice) + if (t.gasPrice == UndefinedU256) t.gasPrice = 10 * dev::eth::szabo; - if (!t.gas) + if (t.gas == UndefinedU256) t.gas = client()->gasLimitRemaining(); - return toJS(client()->call(m_accounts->secretKey(t.from), t.value, t.to, t.data, t.gas, t.gasPrice, jsToBlockNumber(_blockNumber), FudgeFactor::Lenient).output); + return toJS(client()->call(t.from, t.value, t.to, t.data, t.gas, t.gasPrice, jsToBlockNumber(_blockNumber), FudgeFactor::Lenient).output); } catch (...) { BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS)); } - } bool WebThreeStubServerBase::eth_flush() @@ -879,7 +873,7 @@ string WebThreeStubServerBase::eth_register(string const& _address) { try { - return toJS(m_accounts->addProxyAccount(jsToAddress(_address))); + return toJS(m_ethAccounts->addProxyAccount(jsToAddress(_address))); } catch (...) { @@ -891,7 +885,7 @@ bool WebThreeStubServerBase::eth_unregister(string const& _accountId) { try { - return m_accounts->removeProxyAccount(jsToInt(_accountId)); + return m_ethAccounts->removeProxyAccount(jsToInt(_accountId)); } catch (...) { @@ -906,9 +900,9 @@ Json::Value WebThreeStubServerBase::eth_fetchQueuedTransactions(string const& _a auto id = jsToInt(_accountId); Json::Value ret(Json::arrayValue); // TODO: throw an error on no account with given id - for (TransactionSkeleton const& t: m_accounts->getQueuedTransactions(id)) + for (TransactionSkeleton const& t: m_ethAccounts->queuedTransactions(id)) ret.append(toJson(t)); - m_accounts->clearQueue(id); + m_ethAccounts->clearQueue(id); return ret; } catch (...) @@ -934,11 +928,11 @@ bool WebThreeStubServerBase::shh_post(Json::Value const& _json) { shh::Message m = toMessage(_json); Secret from; - if (m.from() && m_ids.count(m.from())) + if (m.from() && m_shhIds.count(m.from())) { cwarn << "Silently signing message from identity" << m.from() << ": User validation hook goes here."; // TODO: insert validification hook here. - from = m_ids[m.from()]; + from = m_shhIds[m.from()]; } face()->inject(toSealed(_json, m, from)); @@ -953,7 +947,7 @@ bool WebThreeStubServerBase::shh_post(Json::Value const& _json) string WebThreeStubServerBase::shh_newIdentity() { KeyPair kp = KeyPair::create(); - m_ids[kp.pub()] = kp.secret(); + m_shhIds[kp.pub()] = kp.secret(); return toJS(kp.pub()); } @@ -961,7 +955,7 @@ bool WebThreeStubServerBase::shh_hasIdentity(string const& _identity) { try { - return m_ids.count(jsToPublic(_identity)) > 0; + return m_shhIds.count(jsToPublic(_identity)) > 0; } catch (...) { @@ -1021,7 +1015,7 @@ Json::Value WebThreeStubServerBase::shh_getFilterChanges(string const& _filterId int id = jsToInt(_filterId); auto pub = m_shhWatches[id]; - if (!pub || m_ids.count(pub)) + if (!pub || m_shhIds.count(pub)) for (h256 const& h: face()->checkWatch(id)) { auto e = face()->envelope(h); @@ -1029,7 +1023,7 @@ Json::Value WebThreeStubServerBase::shh_getFilterChanges(string const& _filterId if (pub) { cwarn << "Silently decrypting message from identity" << pub << ": User validation hook goes here."; - m = e.open(face()->fullTopic(id), m_ids[pub]); + m = e.open(face()->fullTopic(id), m_shhIds[pub]); } else m = e.open(face()->fullTopic(id)); @@ -1054,7 +1048,7 @@ Json::Value WebThreeStubServerBase::shh_getMessages(string const& _filterId) int id = jsToInt(_filterId); auto pub = m_shhWatches[id]; - if (!pub || m_ids.count(pub)) + if (!pub || m_shhIds.count(pub)) for (h256 const& h: face()->watchMessages(id)) { auto e = face()->envelope(h); @@ -1062,7 +1056,7 @@ Json::Value WebThreeStubServerBase::shh_getMessages(string const& _filterId) if (pub) { cwarn << "Silently decrypting message from identity" << pub << ": User validation hook goes here."; - m = e.open(face()->fullTopic(id), m_ids[pub]); + m = e.open(face()->fullTopic(id), m_shhIds[pub]); } else m = e.open(face()->fullTopic(id)); @@ -1077,18 +1071,3 @@ Json::Value WebThreeStubServerBase::shh_getMessages(string const& _filterId) BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS)); } } - -void WebThreeStubServerBase::authenticate(TransactionSkeleton const& _t, bool _toProxy) -{ - if (_toProxy) - m_accounts->queueTransaction(_t); - else if (_t.to) - client()->submitTransaction(m_accounts->secretKey(_t.from), _t.value, _t.to, _t.data, _t.gas, _t.gasPrice); - else - client()->submitTransaction(m_accounts->secretKey(_t.from), _t.value, _t.data, _t.gas, _t.gasPrice); -} - -void WebThreeStubServerBase::setAccounts(const vector& _accounts) -{ - m_accounts->setAccounts(_accounts); -} diff --git a/libweb3jsonrpc/WebThreeStubServerBase.h b/libweb3jsonrpc/WebThreeStubServerBase.h index 3166eefad..f3f7edfe7 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.h +++ b/libweb3jsonrpc/WebThreeStubServerBase.h @@ -36,10 +36,10 @@ namespace dev { class WebThreeNetworkFace; -class AccountHolder; class KeyPair; namespace eth { +class AccountHolder; struct TransactionSkeleton; class Interface; } @@ -68,7 +68,7 @@ public: class WebThreeStubServerBase: public AbstractWebThreeStubServer { public: - WebThreeStubServerBase(jsonrpc::AbstractServerConnector& _conn, std::vector const& _accounts); + WebThreeStubServerBase(jsonrpc::AbstractServerConnector& _conn, std::shared_ptr const& _ethAccounts, std::vector const& _sshAccounts); virtual std::string web3_sha3(std::string const& _param1); virtual std::string web3_clientVersion() { return "C++ (ethereum-cpp)"; } @@ -134,12 +134,8 @@ public: virtual Json::Value shh_getFilterChanges(std::string const& _filterId); virtual Json::Value shh_getMessages(std::string const& _filterId); - void setAccounts(std::vector const& _accounts); void setIdentities(std::vector const& _ids); - std::map const& ids() const { return m_ids; } - -protected: - virtual void authenticate(dev::eth::TransactionSkeleton const& _t, bool _toProxy); + std::map const& ids() const { return m_shhIds; } protected: virtual dev::eth::Interface* client() = 0; @@ -147,9 +143,10 @@ protected: virtual dev::WebThreeNetworkFace* network() = 0; virtual dev::WebThreeStubDatabaseFace* db() = 0; - std::map m_ids; + std::shared_ptr m_ethAccounts; + + std::map m_shhIds; std::map m_shhWatches; - std::shared_ptr m_accounts; }; } //namespace dev diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index fa5ec1c27..a6eadbf4a 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -85,7 +85,8 @@ ClientModel::ClientModel(): connect(this, &ClientModel::runComplete, this, &ClientModel::showDebugger, Qt::QueuedConnection); m_client.reset(new MixClient(QStandardPaths::writableLocation(QStandardPaths::TempLocation).toStdString())); - m_web3Server.reset(new Web3Server(*m_rpcConnector.get(), std::vector(), m_client.get())); + m_ethAccounts = make_shared([=](){return m_client.get();}, std::vector()); + m_web3Server.reset(new Web3Server(*m_rpcConnector.get(), m_ethAccounts, std::vector(), m_client.get())); connect(m_web3Server.get(), &Web3Server::newTransaction, this, &ClientModel::onNewTransaction, Qt::DirectConnection); } @@ -211,7 +212,7 @@ void ClientModel::setupState(QVariantMap _state) QVariantList stateContracts = _state.value("contracts").toList(); QVariantList transactions = _state.value("transactions").toList(); - map accounts; + unordered_map accounts; std::vector userAccounts; for (auto const& b: stateAccounts) @@ -280,11 +281,11 @@ void ClientModel::setupState(QVariantMap _state) transactionSequence.push_back(transactionSettings); } } - m_web3Server->setAccounts(userAccounts); + m_ethAccounts->setAccounts(userAccounts); executeSequence(transactionSequence, accounts, Secret(_state.value("miner").toMap().value("secret").toString().toStdString())); } -void ClientModel::executeSequence(vector const& _sequence, std::map const& _accounts, Secret const& _miner) +void ClientModel::executeSequence(vector const& _sequence, std::unordered_map const& _accounts, Secret const& _miner) { if (m_running) { @@ -315,7 +316,6 @@ void ClientModel::executeSequence(vector const& _sequence, TransactionSettings stdTransaction = transaction; stdTransaction.gasAuto = true; Address address = deployContract(stdContractCode, stdTransaction); - deployedContracts.push_back(address); m_stdContractAddresses[stdTransaction.contractId] = address; m_stdContractNames[address] = stdTransaction.contractId; } @@ -551,7 +551,7 @@ QVariant ClientModel::formatValue(SolidityType const& _type, u256 const& _value) return res; } -QVariant ClientModel::formatStorageValue(SolidityType const& _type, map const& _storage, unsigned _offset, u256 const& _slot) +QVariant ClientModel::formatStorageValue(SolidityType const& _type, unordered_map const& _storage, unsigned _offset, u256 const& _slot) { u256 slot = _slot; QVariantList values; diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 91b66c76c..910c0ed01 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -35,7 +35,7 @@ namespace dev { -namespace eth { class Account; } +namespace eth { class Account; class FixedAccountHolder; } namespace mix { @@ -220,14 +220,14 @@ private: RecordLogEntry* lastBlock() const; QVariantMap contractAddresses() const; QVariantList gasCosts() const; - void executeSequence(std::vector const& _sequence, std::map const& _accounts, Secret const& _miner); + void executeSequence(std::vector const& _sequence, std::unordered_map const& _accounts, Secret const& _miner); dev::Address deployContract(bytes const& _code, TransactionSettings const& _tr = TransactionSettings()); void callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr); void onNewTransaction(); void onStateReset(); void showDebuggerForTransaction(ExecutionResult const& _t); QVariant formatValue(SolidityType const& _type, dev::u256 const& _value); - QVariant formatStorageValue(SolidityType const& _type, std::map const& _storage, unsigned _offset, dev::u256 const& _slot); + QVariant formatStorageValue(SolidityType const& _type, std::unordered_map const& _storage, unsigned _offset, dev::u256 const& _slot); std::atomic m_running; std::atomic m_mining; @@ -235,6 +235,7 @@ private: std::unique_ptr m_client; std::unique_ptr m_rpcConnector; std::unique_ptr m_web3Server; + std::shared_ptr m_ethAccounts; QList m_gasCosts; std::map m_contractAddresses; std::map m_contractNames; diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 636a665e6..5c6ec07c0 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -219,6 +219,19 @@ void CodeModel::reset(QVariantMap const& _documents) emit scheduleCompilationJob(++m_backgroundJobId); } +void CodeModel::unregisterContractSrc(QString const& _documentId) +{ + { + Guard pl(x_pendingContracts); + m_pendingContracts.erase(_documentId); + } + + // launch the background thread + m_compiling = true; + emit stateChanged(); + emit scheduleCompilationJob(++m_backgroundJobId); +} + void CodeModel::registerCodeChange(QString const& _documentId, QString const& _code) { { diff --git a/mix/CodeModel.h b/mix/CodeModel.h index 3f713a17b..a0b03951f 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -160,6 +160,8 @@ public: Q_INVOKABLE CompiledContract* contractByDocumentId(QString const& _documentId) const; /// Reset code model Q_INVOKABLE void reset() { reset(QVariantMap()); } + /// Delete a contract source + Q_INVOKABLE void unregisterContractSrc(QString const& _documentId); /// Convert solidity type info to mix type static SolidityType nodeType(dev::solidity::Type const* _type); /// Check if given location belongs to contract or function diff --git a/mix/ContractCallDataEncoder.cpp b/mix/ContractCallDataEncoder.cpp index 6b29d8b98..07ab8dd73 100644 --- a/mix/ContractCallDataEncoder.cpp +++ b/mix/ContractCallDataEncoder.cpp @@ -36,6 +36,14 @@ using namespace dev::mix; bytes ContractCallDataEncoder::encodedData() { bytes r(m_encodedData); + size_t headerSize = m_encodedData.size() & ~0x1fUL; //ignore any prefix that is not 32-byte aligned + //apply offsets + for (auto const& p: m_offsetMap) + { + vector_ref offsetRef(r.data() + p.first, 32); + toBigEndian>(p.second + headerSize, offsetRef); //add header size minus signature hash + } + r.insert(r.end(), m_dynamicData.begin(), m_dynamicData.end()); return r; } @@ -64,6 +72,9 @@ void ContractCallDataEncoder::encode(QVariant const& _data, SolidityType const& if (_type.dynamicSize) { + bytes empty(32); + size_t sizePos = m_dynamicData.size(); + m_dynamicData += empty; //reserve space for count if (_type.type == SolidityType::Type::Bytes) count = encodeSingleItem(_data.toString(), _type, m_dynamicData); else @@ -72,9 +83,10 @@ void ContractCallDataEncoder::encode(QVariant const& _data, SolidityType const& for (auto const& item: strList) encodeSingleItem(item, _type, m_dynamicData); } - bytes sizeEnc(32); - toBigEndian(count, sizeEnc); - m_encodedData.insert(m_encodedData.end(), sizeEnc.begin(), sizeEnc.end()); + vector_ref sizeRef(m_dynamicData.data() + sizePos, 32); + toBigEndian(count, sizeRef); + m_offsetMap.push_back(std::make_pair(m_encodedData.size(), sizePos)); + m_encodedData += empty; //reserve space for offset } else { diff --git a/mix/ContractCallDataEncoder.h b/mix/ContractCallDataEncoder.h index cab00dd93..2707845ae 100644 --- a/mix/ContractCallDataEncoder.h +++ b/mix/ContractCallDataEncoder.h @@ -73,6 +73,7 @@ private: private: bytes m_encodedData; bytes m_dynamicData; + std::vector> m_offsetMap; }; } diff --git a/mix/FileIo.cpp b/mix/FileIo.cpp index 0991aa63d..22538194c 100644 --- a/mix/FileIo.cpp +++ b/mix/FileIo.cpp @@ -210,3 +210,9 @@ void FileIo::stopWatching(QString const& _path) { m_watcher->removePath(pathFromUrl(_path)); } + +void FileIo::deleteFile(QString const& _path) +{ + QFile file(pathFromUrl(_path)); + file.remove(); +} diff --git a/mix/FileIo.h b/mix/FileIo.h index 33c2bd5fd..90a143120 100644 --- a/mix/FileIo.h +++ b/mix/FileIo.h @@ -66,6 +66,8 @@ public: Q_INVOKABLE void watchFileChanged(QString const& _path); /// Stop Listenning for files change in @arg _path. Q_INVOKABLE void stopWatching(QString const& _path); + /// Delete a file + Q_INVOKABLE void deleteFile(QString const& _path); private: QString getHomePath() const; diff --git a/mix/MachineStates.h b/mix/MachineStates.h index afd2b990a..2a88d83bf 100644 --- a/mix/MachineStates.h +++ b/mix/MachineStates.h @@ -50,7 +50,7 @@ namespace mix dev::u256s stack; dev::bytes memory; dev::bigint gasCost; - std::map storage; + std::unordered_map storage; std::vector levels; unsigned codeIndex; unsigned dataIndex; diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index b1d8f889e..cac208ba4 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -69,14 +69,14 @@ bytes MixBlockChain::createGenesisBlock(h256 _stateRoot) MixClient::MixClient(std::string const& _dbPath): m_dbPath(_dbPath) { - resetState(std::map()); + resetState(std::unordered_map()); } MixClient::~MixClient() { } -void MixClient::resetState(std::map const& _accounts, Secret const& _miner) +void MixClient::resetState(std::unordered_map const& _accounts, Secret const& _miner) { WriteGuard l(x_state); Guard fl(x_filtersWatches); @@ -98,19 +98,30 @@ void MixClient::resetState(std::map const& _accounts, Secret m_executions.clear(); } -Transaction MixClient::replaceGas(Transaction const& _t, Secret const& _secret, u256 const& _gas) +Transaction MixClient::replaceGas(Transaction const& _t, u256 const& _gas, Secret const& _secret) { - if (_t.isCreation()) - return Transaction(_t.value(), _t.gasPrice(), _gas, _t.data(), _t.nonce(), _secret); + Transaction ret; + if (_secret) + { + if (_t.isCreation()) + ret = Transaction(_t.value(), _t.gasPrice(), _gas, _t.data(), _t.nonce(), _secret); + else + ret = Transaction(_t.value(), _t.gasPrice(), _gas, _t.receiveAddress(), _t.data(), _t.nonce(), _secret); + } else - return Transaction(_t.value(), _t.gasPrice(), _gas, _t.receiveAddress(), _t.data(), _t.nonce(), _secret); + { + if (_t.isCreation()) + ret = Transaction(_t.value(), _t.gasPrice(), _gas, _t.data(), _t.nonce()); + else + ret = Transaction(_t.value(), _t.gasPrice(), _gas, _t.receiveAddress(), _t.data(), _t.nonce()); + ret.forceSender(_t.safeSender()); + } + return ret; } void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _call, bool _gasAuto, Secret const& _secret) { - Transaction t = _gasAuto ? replaceGas(_t, _secret, m_state.gasLimitRemaining()) : _t; - bytes rlp = t.rlp(); - + Transaction t = _gasAuto ? replaceGas(_t, m_state.gasLimitRemaining()) : _t; // do debugging run first LastHashes lastHashes(256); lastHashes[0] = bc().numberHash(bc().number()); @@ -120,7 +131,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c State execState = _state; execState.addBalance(t.sender(), t.gas() * t.gasPrice()); //give it enough balance for gas estimation Executive execution(execState, lastHashes, 0); - execution.initialize(&rlp); + execution.initialize(t); execution.execute(); std::vector machineStates; std::vector levels; @@ -219,7 +230,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c // execute on a state if (!_call) { - t = _gasAuto ? replaceGas(_t, _secret, d.gasUsed) : _t; + t = _gasAuto ? replaceGas(_t, d.gasUsed, _secret) : _t; er =_state.execute(lastHashes, t); if (t.isCreation() && _state.code(d.contractAddress).empty()) BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Not enough gas for contract deployment")); @@ -295,18 +306,17 @@ Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes cons return address; } -dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto, FudgeFactor _ff) +dev::eth::ExecutionResult MixClient::call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto, FudgeFactor _ff) { (void)_blockNumber; - Address a = toAddress(_secret); State temp = asOf(eth::PendingBlock); - u256 n = temp.transactionsFrom(a); - Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); + u256 n = temp.transactionsFrom(_from); + Transaction t(_value, _gasPrice, _gas, _dest, _data, n); + t.forceSender(_from); if (_ff == FudgeFactor::Lenient) - temp.addBalance(a, (u256)(t.gasRequired() * t.gasPrice() + t.value())); - bytes rlp = t.rlp(); + temp.addBalance(_from, (u256)(t.gasRequired() * t.gasPrice() + t.value())); WriteGuard lw(x_state); //TODO: lock is required only for last execution state - executeTransaction(t, temp, true, _gasAuto, _secret); + executeTransaction(t, temp, true, _gasAuto); return lastExecution().result; } @@ -320,28 +330,27 @@ Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes cons return submitTransaction(_secret, _endowment, _init, _gas, _gasPrice, false); } -dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, eth::FudgeFactor _ff) +dev::eth::ExecutionResult MixClient::call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, eth::FudgeFactor _ff) { - return call(_secret, _value, _dest, _data, _gas, _gasPrice, _blockNumber, false, _ff); + return call(_from, _value, _dest, _data, _gas, _gasPrice, _blockNumber, false, _ff); } -dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, eth::FudgeFactor _ff) +dev::eth::ExecutionResult MixClient::create(Address const& _from, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, eth::FudgeFactor _ff) { (void)_blockNumber; u256 n; - Address a = toAddress(_secret); State temp; { ReadGuard lr(x_state); temp = asOf(eth::PendingBlock); - n = temp.transactionsFrom(a); + n = temp.transactionsFrom(_from); } - Transaction t(_value, _gasPrice, _gas, _data, n, _secret); + Transaction t(_value, _gasPrice, _gas, _data, n); + t.forceSender(_from); if (_ff == FudgeFactor::Lenient) - temp.addBalance(a, (u256)(t.gasRequired() * t.gasPrice() + t.value())); - bytes rlp = t.rlp(); + temp.addBalance(_from, (u256)(t.gasRequired() * t.gasPrice() + t.value())); WriteGuard lw(x_state); //TODO: lock is required only for last execution state - executeTransaction(t, temp, true, false, _secret); + executeTransaction(t, temp, true, false); return lastExecution().result; } diff --git a/mix/MixClient.h b/mix/MixClient.h index 182e333c2..2c6734234 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -48,19 +48,19 @@ public: MixClient(std::string const& _dbPath); virtual ~MixClient(); /// Reset state to the empty state with given balance. - void resetState(std::map const& _accounts, Secret const& _miner = Secret()); + void resetState(std::unordered_map const& _accounts, Secret const& _miner = Secret()); void mine(); ExecutionResult lastExecution() const; ExecutionResult execution(unsigned _index) const; void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) override; Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) override; - dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override; - dev::eth::ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * eth::szabo, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override; + dev::eth::ExecutionResult call(Address const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override; + dev::eth::ExecutionResult create(Address const& _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * eth::szabo, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override; void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, bool _gasAuto); Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice, bool _gasAuto); - dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber, bool _gasAuto, eth::FudgeFactor _ff = eth::FudgeFactor::Strict); + dev::eth::ExecutionResult call(Address const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber, bool _gasAuto, eth::FudgeFactor _ff = eth::FudgeFactor::Strict); void setAddress(Address _us) override; void startMining() override; @@ -87,9 +87,9 @@ protected: virtual void prepareForTransaction() override {} private: - void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state, bool _call, bool _gasAuto, dev::Secret const& _secret); + void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state, bool _call, bool _gasAuto, dev::Secret const& _secret = dev::Secret()); void noteChanged(h256Set const& _filters); - dev::eth::Transaction replaceGas(dev::eth::Transaction const& _t, dev::Secret const& _secret, dev::u256 const& _gas); + dev::eth::Transaction replaceGas(dev::eth::Transaction const& _t, dev::u256 const& _gas, dev::Secret const& _secret = dev::Secret()); eth::State m_state; eth::State m_startState; diff --git a/mix/Web3Server.cpp b/mix/Web3Server.cpp index 7edc73060..855f33ca5 100644 --- a/mix/Web3Server.cpp +++ b/mix/Web3Server.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "Web3Server.h" using namespace dev::mix; @@ -108,8 +109,8 @@ class EmptyNetwork : public dev::WebThreeNetworkFace } -Web3Server::Web3Server(jsonrpc::AbstractServerConnector& _conn, std::vector const& _accounts, dev::eth::Interface* _client): - WebThreeStubServerBase(_conn, _accounts), +Web3Server::Web3Server(jsonrpc::AbstractServerConnector& _conn, std::shared_ptr const& _ethAccounts, std::vector const& _shhAccounts, dev::eth::Interface* _client): + WebThreeStubServerBase(_conn, _ethAccounts, _shhAccounts), m_client(_client), m_network(new EmptyNetwork()) { diff --git a/mix/Web3Server.h b/mix/Web3Server.h index b8a059295..2383a0a3c 100644 --- a/mix/Web3Server.h +++ b/mix/Web3Server.h @@ -25,6 +25,7 @@ #include #include #include +#include #include namespace dev @@ -38,7 +39,7 @@ class Web3Server: public QObject, public dev::WebThreeStubServerBase, public dev Q_OBJECT public: - Web3Server(jsonrpc::AbstractServerConnector& _conn, std::vector const& _accounts, dev::eth::Interface* _client); + Web3Server(jsonrpc::AbstractServerConnector& _conn, std::shared_ptr const& _ethAccounts, std::vector const& _shhAccounts, dev::eth::Interface* _client); virtual ~Web3Server(); signals: diff --git a/mix/qml/CodeEditorView.qml b/mix/qml/CodeEditorView.qml index e4d62ed81..bb7e203bf 100644 --- a/mix/qml/CodeEditorView.qml +++ b/mix/qml/CodeEditorView.qml @@ -190,9 +190,12 @@ Item { for (var i = 0; i < openDocCount; i++) { var doc = editorListModel.get(i); - var editor = editors.itemAt(i).item; - if (editor) - fileIo.writeFile(doc.path, editor.getText()); + if (editors.itemAt(i)) + { + var editor = editors.itemAt(i).item; + if (editor) + fileIo.writeFile(doc.path, editor.getText()); + } } } @@ -315,6 +318,16 @@ Item { break; } } + + onDocumentRemoved: { + for (var i = 0; i < editorListModel.count; i++) + if (editorListModel.get(i).documentId === documentId) + { + editorListModel.remove(i); + openDocCount--; + break; + } + } } function loadIfNotLoaded () { diff --git a/mix/qml/FilesSection.qml b/mix/qml/FilesSection.qml index d89875583..5e49143a7 100644 --- a/mix/qml/FilesSection.qml +++ b/mix/qml/FilesSection.qml @@ -3,6 +3,7 @@ import QtQuick.Window 2.0 import QtQuick.Layouts 1.0 import QtQuick.Controls 1.0 import QtQuick.Controls.Styles 1.3 +import QtQuick.Dialogs 1.2 import "." @@ -241,8 +242,13 @@ Rectangle anchors.fill: parent acceptedButtons: Qt.LeftButton | Qt.RightButton onClicked:{ - if (mouse.button === Qt.RightButton && !isContract) - contextMenu.popup(); + if (mouse.button === Qt.RightButton) + { + if (isContract) + contextMenuContract.popup(); + else + contextMenu.popup(); + } else if (mouse.button === Qt.LeftButton) { rootItem.isSelected = true; @@ -263,11 +269,32 @@ Rectangle MenuItem { text: qsTr("Delete") onTriggered: { - projectModel.removeDocument(documentId); - wrapperItem.removeDocument(documentId); + deleteConfirmation.open(); } } } + + Menu { + id: contextMenuContract + MenuItem { + text: qsTr("Delete") + onTriggered: { + deleteConfirmation.open(); + } + } + } + + MessageDialog + { + id: deleteConfirmation + text: qsTr("Are you sure to delete this file ?") + standardButtons: StandardIcon.Ok | StandardIcon.Cancel + onAccepted: + { + projectModel.removeDocument(documentId); + wrapperItem.removeDocument(documentId); + } + } } } } diff --git a/mix/qml/js/ProjectModel.js b/mix/qml/js/ProjectModel.js index 6ec906996..6fce7686d 100644 --- a/mix/qml/js/ProjectModel.js +++ b/mix/qml/js/ProjectModel.js @@ -294,7 +294,10 @@ function renameDocument(documentId, newName) { function getDocument(documentId) { var i = getDocumentIndex(documentId); - return projectListModel.get(i); + if (i === -1) + return undefined; + else + return projectListModel.get(i); } function getDocumentIdByName(fileName) @@ -308,10 +311,13 @@ function getDocumentIdByName(fileName) function removeDocument(documentId) { var i = getDocumentIndex(documentId); var document = projectListModel.get(i); - if (!document.isContract) { - projectListModel.remove(i); - documentRemoved(documentId); - } + fileIo.stopWatching(document.path); + fileIo.deleteFile(document.path); + if (document.isContract) + codeModel.unregisterContractSrc(documentId); + projectListModel.remove(i); + saveProjectFile(); + documentRemoved(documentId); } function newHtmlFile() { diff --git a/mix/test/qml/TestMain.qml b/mix/test/qml/TestMain.qml index 829364a99..727d90b25 100644 --- a/mix/test/qml/TestMain.qml +++ b/mix/test/qml/TestMain.qml @@ -113,5 +113,6 @@ TestCase function test_project_contractRename() { TestProject.test_contractRename(); } function test_project_multipleWebPages() { TestProject.test_multipleWebPages(); } function test_project_multipleContractsSameFile() { TestProject.test_multipleContractsSameFile(); } + function test_project_deleteFile() { TestProject.test_deleteFile(); } } diff --git a/mix/test/qml/js/TestDebugger.js b/mix/test/qml/js/TestDebugger.js index 4933136ff..4e295c46f 100644 --- a/mix/test/qml/js/TestDebugger.js +++ b/mix/test/qml/js/TestDebugger.js @@ -223,13 +223,16 @@ function test_ctrTypeAsParam() "}"); mainApplication.projectModel.stateListModel.editState(0); //C1 ctor already added var transactionDialog = mainApplication.projectModel.stateDialog.transactionDialog; + mainApplication.projectModel.stateDialog.model.editTransaction(3); + ts.waitForRendering(transactionDialog, 3000); + clickElement(transactionDialog, 200, 300); + ts.typeString("", transactionDialog); + transactionDialog.acceptAndClose(); mainApplication.projectModel.stateDialog.model.addTransaction(); transactionDialog = mainApplication.projectModel.stateDialog.transactionDialog; ts.waitForRendering(transactionDialog, 3000); transactionDialog.selectContract("C2"); transactionDialog.selectFunction("getFromC1"); - clickElement(transactionDialog, 406, 340); - clickElement(transactionDialog, 406, 366); transactionDialog.acceptAndClose(); mainApplication.projectModel.stateDialog.acceptAndClose(); mainApplication.mainContent.startQuickDebugging(); diff --git a/mix/test/qml/js/TestProject.js b/mix/test/qml/js/TestProject.js index 49b5ea51f..fe1023f05 100644 --- a/mix/test/qml/js/TestProject.js +++ b/mix/test/qml/js/TestProject.js @@ -44,3 +44,17 @@ function test_multipleContractsSameFile() tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel.get(3), "contract", "C2"); tryCompare(mainApplication.mainContent.rightPane.transactionLog.transactionModel.get(4), "contract", "C3"); } + +function test_deleteFile() +{ + newProject(); + var path = mainApplication.projectModel.projectPath; + createHtml("page1.html", "
Fail
"); + createHtml("page2.html", "
Fail
"); + createHtml("page3.html", "
Fail
"); + mainApplication.projectModel.removeDocument("page2.html"); + mainApplication.projectModel.closeProject(function(){}); + mainApplication.projectModel.loadProject(path); + var doc = mainApplication.projectModel.getDocument("page2.html"); + verify(!doc, "page2.html has not been removed"); +} diff --git a/neth/main.cpp b/neth/main.cpp index 066177b2f..7ce64cba5 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -36,8 +36,9 @@ #include #include #include -#if ETH_JSONRPC +#if ETH_JSONRPC || !ETH_TRUE #include +#include #include #endif #include "BuildInfo.h" @@ -573,13 +574,13 @@ int main(int argc, char** argv) if (c && mining) c->startMining(); -#if ETH_JSONRPC +#if ETH_JSONRPC || !ETH_TRUE shared_ptr jsonrpcServer; unique_ptr jsonrpcConnector; if (jsonrpc > -1) { jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads)); - jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, vector({us}))); + jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared([&](){ return web3.ethereum(); }, vector({us})), vector({us}))); jsonrpcServer->setIdentities({us}); jsonrpcServer->StartListening(); } @@ -793,7 +794,7 @@ int main(int argc, char** argv) #else jsonrpcConnector = unique_ptr(new jsonrpc::HttpServer(jsonrpc, "", "", 4)); #endif - jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, vector({us}))); + jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared([&](){ return web3.ethereum(); }, vector({us})), vector({us}))); jsonrpcServer->setIdentities({us}); jsonrpcServer->StartListening(); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a97bb86fc..39a235c58 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -25,6 +25,11 @@ add_subdirectory(libethereum) add_subdirectory(libevm) add_subdirectory(libnatspec) add_subdirectory(libp2p) + +if (JSCONSOLE) + add_subdirectory(libjsengine) +endif() + if (SOLIDITY) add_subdirectory(libsolidity) endif () @@ -41,6 +46,10 @@ include_directories(${Boost_INCLUDE_DIRS}) include_directories(${CRYPTOPP_INCLUDE_DIRS}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) +if (JSCONSOLE) + include_directories(${V8_INCLUDE_DIRS}) +endif() + # search for test names and create ctest tests enable_testing() foreach(file ${SRC_LIST}) @@ -65,14 +74,22 @@ target_link_libraries(testeth ${CURL_LIBRARIES}) target_link_libraries(testeth ethereum) target_link_libraries(testeth ethcore) target_link_libraries(testeth secp256k1) + +if (JSCONSOLE) + target_link_libraries(testeth jsengine) +endif() + if (SOLIDITY) target_link_libraries(testeth solidity) endif () + target_link_libraries(testeth testutils) + if (GUI AND NOT JUSTTESTS) target_link_libraries(testeth webthree) target_link_libraries(testeth natspec) endif() + if (JSONRPC) target_link_libraries(testeth web3jsonrpc) target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARIES}) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 3171f91cb..32b76f974 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -305,7 +305,7 @@ void ImportTest::checkExpectedState(State const& _stateExpect, State const& _sta if (addressOptions.m_bHasStorage) { - map stateStorage = _statePost.storage(a.first); + unordered_map stateStorage = _statePost.storage(a.first); for (auto const& s: _stateExpect.storage(a.first)) CHECK(stateStorage[s.first] == s.second, "Check State: " << a.first << ": incorrect storage [" << s.first << "] = " << toHex(stateStorage[s.first]) << ", expected [" << s.first << "] = " << toHex(s.second)); diff --git a/test/fuzzTesting/checkRandomStateTest.cpp b/test/fuzzTesting/checkRandomStateTest.cpp index 719798620..01366cd4d 100644 --- a/test/fuzzTesting/checkRandomStateTest.cpp +++ b/test/fuzzTesting/checkRandomStateTest.cpp @@ -173,7 +173,7 @@ bool doStateTest(mValue& _v) } //checkStorage(importer.m_statePost.storage(expectedAddr), theState.storage(expectedAddr), expectedAddr); - map _resultStore = theState.storage(expectedAddr); + unordered_map _resultStore = theState.storage(expectedAddr); for (auto&& expectedStorePair : importer.m_statePost.storage(expectedAddr)) { diff --git a/test/libdevcrypto/crypto.cpp b/test/libdevcrypto/crypto.cpp index 96826bdf9..88ff98965 100644 --- a/test/libdevcrypto/crypto.cpp +++ b/test/libdevcrypto/crypto.cpp @@ -593,15 +593,14 @@ BOOST_AUTO_TEST_CASE(ecies_aes128_ctr_unaligned) // TESTING: send encrypt magic sequence bytes magic {0x22,0x40,0x08,0x91}; bytes magicCipherAndMac; - encryptSymNoAuth(encryptK, &magic, magicCipherAndMac, h128()); + magicCipherAndMac = encryptSymNoAuth(encryptK, h128(), &magic); magicCipherAndMac.resize(magicCipherAndMac.size() + 32); sha3mac(egressMac.ref(), &magic, egressMac.ref()); egressMac.ref().copyTo(bytesRef(&magicCipherAndMac).cropped(magicCipherAndMac.size() - 32, 32)); - bytes plaintext; bytesConstRef cipher(&magicCipherAndMac[0], magicCipherAndMac.size() - 32); - decryptSymNoAuth(encryptK, h128(), cipher, plaintext); + bytes plaintext = decryptSymNoAuth(encryptK, h128(), cipher); plaintext.resize(magic.size()); BOOST_REQUIRE(plaintext.size() > 0); @@ -615,10 +614,10 @@ BOOST_AUTO_TEST_CASE(ecies_aes128_ctr) bytesConstRef msg((byte*)m.data(), m.size()); bytes ciphertext; - auto iv = encryptSymNoAuth(k, msg, ciphertext); + h128 iv; + tie(ciphertext, iv) = encryptSymNoAuth(k, msg); - bytes plaintext; - decryptSymNoAuth(k, iv, &ciphertext, plaintext); + bytes plaintext = decryptSymNoAuth(k, iv, &ciphertext); BOOST_REQUIRE_EQUAL(asString(plaintext), m); } diff --git a/test/libethcore/dagger.cpp b/test/libethcore/dagger.cpp index 119780346..4faf0a283 100644 --- a/test/libethcore/dagger.cpp +++ b/test/libethcore/dagger.cpp @@ -63,14 +63,14 @@ BOOST_AUTO_TEST_CASE(basic_test) unsigned cacheSize(o["cache_size"].get_int()); h256 cacheHash(o["cache_hash"].get_str()); - BOOST_REQUIRE_EQUAL(EthashAux::get()->params(header).cache_size, cacheSize); + BOOST_REQUIRE_EQUAL(EthashAux::get()->light(header)->size, cacheSize); BOOST_REQUIRE_EQUAL(sha3(EthashAux::get()->light(header)->data()), cacheHash); #if TEST_FULL unsigned fullSize(o["full_size"].get_int()); h256 fullHash(o["full_hash"].get_str()); - BOOST_REQUIRE_EQUAL(EthashAux::get()->full(header).size(), fullSize); - BOOST_REQUIRE_EQUAL(sha3(EthashAux::get()->full(header)), fullHash); + BOOST_REQUIRE_EQUAL(EthashAux::get()->full(header)->size(), fullSize); + BOOST_REQUIRE_EQUAL(sha3(EthashAux::get()->full(header)->data()), fullHash); #endif h256 result(o["result"].get_str()); diff --git a/test/libethereum/BlockTestsFiller/bcTotalDifficultyTestFiller.json b/test/libethereum/BlockTestsFiller/bcTotalDifficultyTestFiller.json new file mode 100644 index 000000000..1acaa23e9 --- /dev/null +++ b/test/libethereum/BlockTestsFiller/bcTotalDifficultyTestFiller.json @@ -0,0 +1,1596 @@ +{ + "sideChainWithMoreTransactions" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "131072", + "extraData" : "0x42", + "gasLimit" : "3141592", + "gasUsed" : "0", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0x0102030405060708", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "40" + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "nonce" : "4" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "blocknumber" : "1", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "2", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "31059", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "300" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "0x3453454", + "gasLimit" : "31509", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "300" + }, + { + "data" : "", + "gasLimit" : "31509", + "gasPrice" : "1", + "nonce" : "4", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "195e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "300" + } + ], + "uncleHeaders" : [ + ] + } + ] + }, + + "lotsOfBranchesOverrideAtTheEnd" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "131072", + "extraData" : "0x42", + "gasLimit" : "3141592", + "gasUsed" : "0", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0x0102030405060708", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "820" + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "nonce" : "4" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "blocknumber" : "1", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "2", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314134359", + "gasPrice" : "1343", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "0x34235435346", + "gasLimit" : "314143359", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "3331", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "200" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "0x44634634", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "200" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "31059", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "300" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "0x3453454", + "gasLimit" : "31509", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "300" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "795e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1000" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "31400", + "gasPrice" : "100000000", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "400" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "10", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "400" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "5", + "transactions" : [ + { + "data" : "0x44634634", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "400" + } + ], + "uncleHeaders" : [ + ] + } + ] + }, + + "lotsOfBranchesOverrideAtTheMiddle" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "131072", + "extraData" : "0x42", + "gasLimit" : "3141592", + "gasUsed" : "0", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0x0102030405060708", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "420" + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "nonce" : "4" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "blocknumber" : "1", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "2", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314134359", + "gasPrice" : "1343", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "0x34235435346", + "gasLimit" : "314143359", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "3331", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "200" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "0x44634634", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "200" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "5", + "transactions" : [ + { + "data" : "0x44634634", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "200" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "31059", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "300" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "0x3453454", + "gasLimit" : "31509", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "300" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "795e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1000" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "31400", + "gasPrice" : "100000000", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "400" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "10", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "400" + } + ], + "uncleHeaders" : [ + ] + } + ] + }, + + "lotsOfBranches" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "131072", + "extraData" : "0x42", + "gasLimit" : "3141592", + "gasUsed" : "0", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0x0102030405060708", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "40" + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "nonce" : "4" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "blocknumber" : "1", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "2", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314134359", + "gasPrice" : "1343", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "0x34235435346", + "gasLimit" : "314143359", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "3331", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "200" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "0x44634634", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "200" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "31059", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "300" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "0x3453454", + "gasLimit" : "31509", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "300" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "795e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1000" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "31400", + "gasPrice" : "100000000", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "400" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "10", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "400" + } + ], + "uncleHeaders" : [ + ] + } + ] + }, + + "lotsOfLeafs" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "131072", + "extraData" : "0x42", + "gasLimit" : "3141592", + "gasUsed" : "0", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0x0102030405060708", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1" + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "nonce" : "3" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "blocknumber" : "1", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "2", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "0" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314134359", + "gasPrice" : "1343", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "2" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "0x34235435346", + "gasLimit" : "314143359", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "3" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "3331", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "4" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "0x44634634", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "31059", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "6" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "0x3453454", + "gasLimit" : "31509", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "7" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "795e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "9" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "31400", + "gasPrice" : "100000000000", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "10", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "11" + } + ], + "uncleHeaders" : [ + ] + } + ] + }, + + "sideChainWithNewMaxDifficultyStartingFromBlock3AfterBlock4" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "131072", + "extraData" : "0x42", + "gasLimit" : "3141592", + "gasUsed" : "0", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0x0102030405060708", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "45" + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "nonce" : "5" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "blocknumber" : "1", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "2", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "3" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "7" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "11" + } + ], + "uncleHeaders" : [ + { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "0x020040", + "extraData" : "0x", + "gasLimit" : "0x2fefd8", + "gasUsed" : "0x5208", + "hash" : "9168fbfb2e3fbedfdb9eac6f73b6d7c9323c957fc3406f27a2f44983f0e5dd43", + "mixHash" : "d56ea25bfefc68484759c3dd934030624308b7ab02bb20aee17852aff72f1397", + "nonce" : "6e7970f59660cbd7", + "number" : "0x02", + "parentHash" : "b7afc3043361f44fd15c0f8df8ebab8284d01c8f79fb47b6fc75eec98b4b4683", + "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "a2a5e3d96e902272adb58e90c364f7b92684c539e0ded77356cf33d966f917fe", + "timestamp" : "0x553e25de", + "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + } + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "13" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "5", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "4", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "17" + } + ], + "uncleHeaders" : [ + ] + } + ] + }, + + "uncleBlockAtBlock3afterBlock4" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "131072", + "extraData" : "0x42", + "gasLimit" : "3141592", + "gasUsed" : "0", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0x0102030405060708", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "16" + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "nonce" : "4" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "blocknumber" : "1", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "2", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "3" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "4", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "7" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "11" + } + ], + "uncleHeaders" : [ + { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "0x020040", + "extraData" : "0x", + "gasLimit" : "0x2fefd8", + "gasUsed" : "0x5208", + "hash" : "9168fbfb2e3fbedfdb9eac6f73b6d7c9323c957fc3406f27a2f44983f0e5dd43", + "mixHash" : "d56ea25bfefc68484759c3dd934030624308b7ab02bb20aee17852aff72f1397", + "nonce" : "6e7970f59660cbd7", + "number" : "0x02", + "parentHash" : "b7afc3043361f44fd15c0f8df8ebab8284d01c8f79fb47b6fc75eec98b4b4683", + "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "a2a5e3d96e902272adb58e90c364f7b92684c539e0ded77356cf33d966f917fe", + "timestamp" : "0x553e25de", + "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + } + ] + } + ] + }, + + "uncleBlockAtBlock3AfterBlock3" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "131072", + "extraData" : "0x42", + "gasLimit" : "3141592", + "gasUsed" : "0", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0x0102030405060708", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "9" + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "nonce" : "3" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "blocknumber" : "1", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "1" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "2", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "3" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5" + } + ], + "uncleHeaders" : [ + ] + }, + { + "blocknumber" : "3", + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "7" + } + ], + "uncleHeaders" : [ + { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "0x020040", + "extraData" : "0x", + "gasLimit" : "0x2fefd8", + "gasUsed" : "0x5208", + "hash" : "9168fbfb2e3fbedfdb9eac6f73b6d7c9323c957fc3406f27a2f44983f0e5dd43", + "mixHash" : "d56ea25bfefc68484759c3dd934030624308b7ab02bb20aee17852aff72f1397", + "nonce" : "6e7970f59660cbd7", + "number" : "0x02", + "parentHash" : "b7afc3043361f44fd15c0f8df8ebab8284d01c8f79fb47b6fc75eec98b4b4683", + "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "a2a5e3d96e902272adb58e90c364f7b92684c539e0ded77356cf33d966f917fe", + "timestamp" : "0x553e25de", + "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + } + ] + } + ] + } +} diff --git a/test/libethereum/blockchain.cpp b/test/libethereum/blockchain.cpp index 9eddb4657..2f76e43ae 100644 --- a/test/libethereum/blockchain.cpp +++ b/test/libethereum/blockchain.cpp @@ -48,26 +48,35 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) { for (auto& i: _v.get_obj()) { - cerr << i.first << endl; mObject& o = i.second.get_obj(); + if (test::Options::get().singleTest && test::Options::get().singleTestName != i.first) + { + o.clear(); + continue; + } + cerr << i.first << endl; BOOST_REQUIRE(o.count("genesisBlockHeader")); BlockInfo biGenesisBlock = constructBlock(o["genesisBlockHeader"].get_obj()); BOOST_REQUIRE(o.count("pre")); ImportTest importer(o["pre"].get_obj()); - TransientDirectory td_stateDB; TransientDirectory td_stateDB_tmp; - State state(State::openDB(td_stateDB.path()), BaseState::Empty, biGenesisBlock.coinbaseAddress); - State stateTemp(State::openDB(td_stateDB_tmp.path()), BaseState::Empty, biGenesisBlock.coinbaseAddress); - importer.importState(o["pre"].get_obj(), state); - o["pre"] = fillJsonWithState(state); - state.commit(); + State trueState(OverlayDB(State::openDB(td_stateDB_tmp.path())), BaseState::Empty, biGenesisBlock.coinbaseAddress); + + //Imported blocks from the start + typedef std::vector uncleList; + typedef std::pair blockSet; + std::vector blockSets; + + importer.importState(o["pre"].get_obj(), trueState); + o["pre"] = fillJsonWithState(trueState); + trueState.commit(); if (_fillin) - biGenesisBlock.stateRoot = state.rootHash(); + biGenesisBlock.stateRoot = trueState.rootHash(); else - BOOST_CHECK_MESSAGE(biGenesisBlock.stateRoot == state.rootHash(), "root hash does not match"); + BOOST_CHECK_MESSAGE(biGenesisBlock.stateRoot == trueState.rootHash(), "root hash does not match"); if (_fillin) { @@ -83,20 +92,55 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) biGenesisBlock.verifyInternals(&rlpGenesisBlock.out()); o["genesisRLP"] = toHex(rlpGenesisBlock.out(), 2, HexPrefix::Add); - // construct blockchain + // construct true blockchain TransientDirectory td; - BlockChain bc(rlpGenesisBlock.out(), td.path(), WithExisting::Kill); + BlockChain trueBc(rlpGenesisBlock.out(), td.path(), WithExisting::Kill); if (_fillin) { BOOST_REQUIRE(o.count("blocks")); mArray blArray; + + blockSet genesis; + genesis.first = rlpGenesisBlock.out(); + genesis.second = uncleList(); + blockSets.push_back(genesis); vector vBiBlocks; vBiBlocks.push_back(biGenesisBlock); + + size_t importBlockNumber = 0; for (auto const& bl: o["blocks"].get_array()) { - stateTemp = state; mObject blObj = bl.get_obj(); + if (blObj.count("blocknumber") > 0) + importBlockNumber = std::max((int)toInt(blObj["blocknumber"]), 1); + else + importBlockNumber++; + + //each time construct a new blockchain up to importBlockNumber (to generate next block header) + vBiBlocks.clear(); + vBiBlocks.push_back(biGenesisBlock); + + TransientDirectory td_stateDB, td_bc; + BlockChain bc(rlpGenesisBlock.out(), td_bc.path(), WithExisting::Kill); + State state(OverlayDB(State::openDB(td_stateDB.path())), BaseState::Empty, biGenesisBlock.coinbaseAddress); + importer.importState(o["pre"].get_obj(), state); + state.commit(); + + for (size_t i = 1; i < importBlockNumber; i++) //0 block is genesis + { + BlockQueue uncleQueue; + uncleList uncles = blockSets.at(i).second; + for (size_t j = 0; j < uncles.size(); j++) + uncleQueue.import(&uncles.at(j), bc); + + const bytes block = blockSets.at(i).first; + bc.sync(uncleQueue, state.db(), 4); + bc.attemptImport(block, state.db()); + vBiBlocks.push_back(BlockInfo(block)); + + state.sync(bc); + } // get txs TransactionQueue txs; @@ -115,6 +159,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) blObj["uncleHeaders"] = importUncles(blObj, vBiUncles, vBiBlocks); BlockQueue uncleBlockQueue; + uncleList uncleBlockQueueList; cnote << "import uncle in blockQueue"; for (size_t i = 0; i < vBiUncles.size(); i++) { @@ -122,6 +167,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) try { uncleBlockQueue.import(&uncle.out(), bc); + uncleBlockQueueList.push_back(uncle.out()); } catch(...) { @@ -205,6 +251,25 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) bc.import(block2.out(), state.db()); state.sync(bc); state.commit(); + + //there we get new blockchain status in state which could have more difficulty than we have in trueState + //attempt to import new block to the true blockchain + trueBc.sync(uncleBlockQueue, trueState.db(), 4); + trueBc.attemptImport(block2.out(), trueState.db()); + trueState.sync(trueBc); + + blockSet newBlock; + newBlock.first = block2.out(); + newBlock.second = uncleBlockQueueList; + if (importBlockNumber < blockSets.size()) + { + //make new correct history of imported blocks + blockSets[importBlockNumber] = newBlock; + for (size_t i = importBlockNumber + 1; i < blockSets.size(); i++) + blockSets.pop_back(); + } + else + blockSets.push_back(newBlock); } // if exception is thrown, RLP is invalid and no blockHeader, Transaction list, or Uncle list should be given catch (...) @@ -213,7 +278,6 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) blObj.erase(blObj.find("blockHeader")); blObj.erase(blObj.find("uncleHeaders")); blObj.erase(blObj.find("transactions")); - state = stateTemp; //revert state as if it was before executing this block } blArray.push_back(blObj); this_thread::sleep_for(chrono::seconds(1)); @@ -224,14 +288,15 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) stateOptionsMap expectStateMap; State stateExpect(OverlayDB(), BaseState::Empty, biGenesisBlock.coinbaseAddress); importer.importState(o["expect"].get_obj(), stateExpect, expectStateMap); - ImportTest::checkExpectedState(stateExpect, state, expectStateMap, Options::get().checkState ? WhenError::Throw : WhenError::DontThrow); + ImportTest::checkExpectedState(stateExpect, trueState, expectStateMap, Options::get().checkState ? WhenError::Throw : WhenError::DontThrow); o.erase(o.find("expect")); } o["blocks"] = blArray; - o["postState"] = fillJsonWithState(state); + o["postState"] = fillJsonWithState(trueState); + o["lastblockhash"] = toString(trueBc.info().hash()); - //make all values hex + //make all values hex in pre section State prestate(OverlayDB(), BaseState::Empty, biGenesisBlock.coinbaseAddress); importer.importState(o["pre"].get_obj(), prestate); o["pre"] = fillJsonWithState(prestate); @@ -241,14 +306,17 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) { for (auto const& bl: o["blocks"].get_array()) { + bool importedAndBest = true; mObject blObj = bl.get_obj(); bytes blockRLP; try { - state.sync(bc); blockRLP = importByteArray(blObj["rlp"].get_str()); - bc.import(blockRLP, state.db()); - state.sync(bc); + trueState.sync(trueBc); + trueBc.import(blockRLP, trueState.db()); + if (trueBc.info() != BlockInfo(blockRLP)) + importedAndBest = false; + trueState.sync(trueBc); } // if exception is thrown, RLP is invalid and no blockHeader, Transaction list, or Uncle list should be given catch (Exception const& _e) @@ -284,124 +352,131 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) const RLP c_blockHeaderRLP(c_rlpBytesBlockHeader); blockHeaderFromFields.populateFromHeader(c_blockHeaderRLP, IgnoreNonce); - BlockInfo blockFromRlp = bc.info(); - - //Check the fields restored from RLP to original fields - BOOST_CHECK_MESSAGE(blockHeaderFromFields.headerHash(WithNonce) == blockFromRlp.headerHash(WithNonce), "hash in given RLP not matching the block hash!"); - BOOST_CHECK_MESSAGE(blockHeaderFromFields.parentHash == blockFromRlp.parentHash, "parentHash in given RLP not matching the block parentHash!"); - BOOST_CHECK_MESSAGE(blockHeaderFromFields.sha3Uncles == blockFromRlp.sha3Uncles, "sha3Uncles in given RLP not matching the block sha3Uncles!"); - BOOST_CHECK_MESSAGE(blockHeaderFromFields.coinbaseAddress == blockFromRlp.coinbaseAddress,"coinbaseAddress in given RLP not matching the block coinbaseAddress!"); - BOOST_CHECK_MESSAGE(blockHeaderFromFields.stateRoot == blockFromRlp.stateRoot, "stateRoot in given RLP not matching the block stateRoot!"); - BOOST_CHECK_MESSAGE(blockHeaderFromFields.transactionsRoot == blockFromRlp.transactionsRoot, "transactionsRoot in given RLP not matching the block transactionsRoot!"); - BOOST_CHECK_MESSAGE(blockHeaderFromFields.receiptsRoot == blockFromRlp.receiptsRoot, "receiptsRoot in given RLP not matching the block receiptsRoot!"); - BOOST_CHECK_MESSAGE(blockHeaderFromFields.logBloom == blockFromRlp.logBloom, "logBloom in given RLP not matching the block logBloom!"); - BOOST_CHECK_MESSAGE(blockHeaderFromFields.difficulty == blockFromRlp.difficulty, "difficulty in given RLP not matching the block difficulty!"); - BOOST_CHECK_MESSAGE(blockHeaderFromFields.number == blockFromRlp.number, "number in given RLP not matching the block number!"); - BOOST_CHECK_MESSAGE(blockHeaderFromFields.gasLimit == blockFromRlp.gasLimit,"gasLimit in given RLP not matching the block gasLimit!"); - BOOST_CHECK_MESSAGE(blockHeaderFromFields.gasUsed == blockFromRlp.gasUsed, "gasUsed in given RLP not matching the block gasUsed!"); - BOOST_CHECK_MESSAGE(blockHeaderFromFields.timestamp == blockFromRlp.timestamp, "timestamp in given RLP not matching the block timestamp!"); - BOOST_CHECK_MESSAGE(blockHeaderFromFields.extraData == blockFromRlp.extraData, "extraData in given RLP not matching the block extraData!"); - BOOST_CHECK_MESSAGE(blockHeaderFromFields.mixHash == blockFromRlp.mixHash, "mixHash in given RLP not matching the block mixHash!"); - BOOST_CHECK_MESSAGE(blockHeaderFromFields.nonce == blockFromRlp.nonce, "nonce in given RLP not matching the block nonce!"); - - BOOST_CHECK_MESSAGE(blockHeaderFromFields == blockFromRlp, "However, blockHeaderFromFields != blockFromRlp!"); - - //Check transaction list + BlockInfo blockFromRlp = trueBc.info(); - Transactions txsFromField; - - for (auto const& txObj: blObj["transactions"].get_array()) + if (importedAndBest) { - mObject tx = txObj.get_obj(); - - BOOST_REQUIRE(tx.count("nonce")); - BOOST_REQUIRE(tx.count("gasPrice")); - BOOST_REQUIRE(tx.count("gasLimit")); - BOOST_REQUIRE(tx.count("to")); - BOOST_REQUIRE(tx.count("value")); - BOOST_REQUIRE(tx.count("v")); - BOOST_REQUIRE(tx.count("r")); - BOOST_REQUIRE(tx.count("s")); - BOOST_REQUIRE(tx.count("data")); - - try - { - Transaction t(createRLPStreamFromTransactionFields(tx).out(), CheckTransaction::Everything); - txsFromField.push_back(t); - } - catch (Exception const& _e) + //Check the fields restored from RLP to original fields + BOOST_CHECK_MESSAGE(blockHeaderFromFields.headerHash(WithNonce) == blockFromRlp.headerHash(WithNonce), "hash in given RLP not matching the block hash!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.parentHash == blockFromRlp.parentHash, "parentHash in given RLP not matching the block parentHash!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.sha3Uncles == blockFromRlp.sha3Uncles, "sha3Uncles in given RLP not matching the block sha3Uncles!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.coinbaseAddress == blockFromRlp.coinbaseAddress,"coinbaseAddress in given RLP not matching the block coinbaseAddress!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.stateRoot == blockFromRlp.stateRoot, "stateRoot in given RLP not matching the block stateRoot!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.transactionsRoot == blockFromRlp.transactionsRoot, "transactionsRoot in given RLP not matching the block transactionsRoot!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.receiptsRoot == blockFromRlp.receiptsRoot, "receiptsRoot in given RLP not matching the block receiptsRoot!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.logBloom == blockFromRlp.logBloom, "logBloom in given RLP not matching the block logBloom!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.difficulty == blockFromRlp.difficulty, "difficulty in given RLP not matching the block difficulty!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.number == blockFromRlp.number, "number in given RLP not matching the block number!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.gasLimit == blockFromRlp.gasLimit,"gasLimit in given RLP not matching the block gasLimit!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.gasUsed == blockFromRlp.gasUsed, "gasUsed in given RLP not matching the block gasUsed!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.timestamp == blockFromRlp.timestamp, "timestamp in given RLP not matching the block timestamp!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.extraData == blockFromRlp.extraData, "extraData in given RLP not matching the block extraData!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.mixHash == blockFromRlp.mixHash, "mixHash in given RLP not matching the block mixHash!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.nonce == blockFromRlp.nonce, "nonce in given RLP not matching the block nonce!"); + + BOOST_CHECK_MESSAGE(blockHeaderFromFields == blockFromRlp, "However, blockHeaderFromFields != blockFromRlp!"); + + //Check transaction list + + Transactions txsFromField; + + for (auto const& txObj: blObj["transactions"].get_array()) { - BOOST_ERROR("Failed transaction constructor with Exception: " << diagnostic_information(_e)); + mObject tx = txObj.get_obj(); + + BOOST_REQUIRE(tx.count("nonce")); + BOOST_REQUIRE(tx.count("gasPrice")); + BOOST_REQUIRE(tx.count("gasLimit")); + BOOST_REQUIRE(tx.count("to")); + BOOST_REQUIRE(tx.count("value")); + BOOST_REQUIRE(tx.count("v")); + BOOST_REQUIRE(tx.count("r")); + BOOST_REQUIRE(tx.count("s")); + BOOST_REQUIRE(tx.count("data")); + + try + { + Transaction t(createRLPStreamFromTransactionFields(tx).out(), CheckTransaction::Everything); + txsFromField.push_back(t); + } + catch (Exception const& _e) + { + BOOST_ERROR("Failed transaction constructor with Exception: " << diagnostic_information(_e)); + } + catch (exception const& _e) + { + cnote << _e.what(); + } } - catch (exception const& _e) + + Transactions txsFromRlp; + RLP root(blockRLP); + for (auto const& tr: root[1]) { - cnote << _e.what(); + Transaction tx(tr.data(), CheckTransaction::Everything); + txsFromRlp.push_back(tx); } - } - Transactions txsFromRlp; - RLP root(blockRLP); - for (auto const& tr: root[1]) - { - Transaction tx(tr.data(), CheckTransaction::Everything); - txsFromRlp.push_back(tx); - } - - BOOST_CHECK_MESSAGE(txsFromRlp.size() == txsFromField.size(), "transaction list size does not match"); + BOOST_CHECK_MESSAGE(txsFromRlp.size() == txsFromField.size(), "transaction list size does not match"); - for (size_t i = 0; i < txsFromField.size(); ++i) - { - BOOST_CHECK_MESSAGE(txsFromField[i].data() == txsFromRlp[i].data(), "transaction data in rlp and in field do not match"); - BOOST_CHECK_MESSAGE(txsFromField[i].gas() == txsFromRlp[i].gas(), "transaction gasLimit in rlp and in field do not match"); - BOOST_CHECK_MESSAGE(txsFromField[i].gasPrice() == txsFromRlp[i].gasPrice(), "transaction gasPrice in rlp and in field do not match"); - BOOST_CHECK_MESSAGE(txsFromField[i].nonce() == txsFromRlp[i].nonce(), "transaction nonce in rlp and in field do not match"); - BOOST_CHECK_MESSAGE(txsFromField[i].signature().r == txsFromRlp[i].signature().r, "transaction r in rlp and in field do not match"); - BOOST_CHECK_MESSAGE(txsFromField[i].signature().s == txsFromRlp[i].signature().s, "transaction s in rlp and in field do not match"); - BOOST_CHECK_MESSAGE(txsFromField[i].signature().v == txsFromRlp[i].signature().v, "transaction v in rlp and in field do not match"); - BOOST_CHECK_MESSAGE(txsFromField[i].receiveAddress() == txsFromRlp[i].receiveAddress(), "transaction receiveAddress in rlp and in field do not match"); - BOOST_CHECK_MESSAGE(txsFromField[i].value() == txsFromRlp[i].value(), "transaction receiveAddress in rlp and in field do not match"); - - BOOST_CHECK_MESSAGE(txsFromField[i] == txsFromRlp[i], "transactions from rlp and transaction from field do not match"); - BOOST_CHECK_MESSAGE(txsFromField[i].rlp() == txsFromRlp[i].rlp(), "transactions rlp do not match"); - } + for (size_t i = 0; i < txsFromField.size(); ++i) + { + BOOST_CHECK_MESSAGE(txsFromField[i].data() == txsFromRlp[i].data(), "transaction data in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].gas() == txsFromRlp[i].gas(), "transaction gasLimit in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].gasPrice() == txsFromRlp[i].gasPrice(), "transaction gasPrice in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].nonce() == txsFromRlp[i].nonce(), "transaction nonce in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].signature().r == txsFromRlp[i].signature().r, "transaction r in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].signature().s == txsFromRlp[i].signature().s, "transaction s in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].signature().v == txsFromRlp[i].signature().v, "transaction v in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].receiveAddress() == txsFromRlp[i].receiveAddress(), "transaction receiveAddress in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].value() == txsFromRlp[i].value(), "transaction receiveAddress in rlp and in field do not match"); + + BOOST_CHECK_MESSAGE(txsFromField[i] == txsFromRlp[i], "transactions from rlp and transaction from field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].rlp() == txsFromRlp[i].rlp(), "transactions rlp do not match"); + } - // check uncle list + // check uncle list - // uncles from uncle list field - vector uBlHsFromField; - if (blObj["uncleHeaders"].type() != json_spirit::null_type) - for (auto const& uBlHeaderObj: blObj["uncleHeaders"].get_array()) - { - mObject uBlH = uBlHeaderObj.get_obj(); - BOOST_REQUIRE(uBlH.size() == 16); - bytes uncleRLP = createBlockRLPFromFields(uBlH); - const RLP c_uRLP(uncleRLP); - BlockInfo uncleBlockHeader; - try - { - uncleBlockHeader.populateFromHeader(c_uRLP); - } - catch(...) + // uncles from uncle list field + vector uBlHsFromField; + if (blObj["uncleHeaders"].type() != json_spirit::null_type) + for (auto const& uBlHeaderObj: blObj["uncleHeaders"].get_array()) { - BOOST_ERROR("invalid uncle header"); + mObject uBlH = uBlHeaderObj.get_obj(); + BOOST_REQUIRE(uBlH.size() == 16); + bytes uncleRLP = createBlockRLPFromFields(uBlH); + const RLP c_uRLP(uncleRLP); + BlockInfo uncleBlockHeader; + try + { + uncleBlockHeader.populateFromHeader(c_uRLP); + } + catch(...) + { + BOOST_ERROR("invalid uncle header"); + } + uBlHsFromField.push_back(uncleBlockHeader); } - uBlHsFromField.push_back(uncleBlockHeader); + + // uncles from block RLP + vector uBlHsFromRlp; + for (auto const& uRLP: root[2]) + { + BlockInfo uBl; + uBl.populateFromHeader(uRLP); + uBlHsFromRlp.push_back(uBl); } - // uncles from block RLP - vector uBlHsFromRlp; - for (auto const& uRLP: root[2]) - { - BlockInfo uBl; - uBl.populateFromHeader(uRLP); - uBlHsFromRlp.push_back(uBl); - } + BOOST_REQUIRE_EQUAL(uBlHsFromField.size(), uBlHsFromRlp.size()); - BOOST_REQUIRE_EQUAL(uBlHsFromField.size(), uBlHsFromRlp.size()); + for (size_t i = 0; i < uBlHsFromField.size(); ++i) + BOOST_CHECK_MESSAGE(uBlHsFromField[i] == uBlHsFromRlp[i], "block header in rlp and in field do not match"); + }//importedAndBest + }//all blocks - for (size_t i = 0; i < uBlHsFromField.size(); ++i) - BOOST_CHECK_MESSAGE(uBlHsFromField[i] == uBlHsFromRlp[i], "block header in rlp and in field do not match"); - } + BOOST_REQUIRE(o.count("lastblockhash") > 0); + BOOST_CHECK_MESSAGE(toString(trueBc.info().hash()) == o["lastblockhash"].get_str(), + "Boost check: " + i.first + " lastblockhash does not match " + toString(trueBc.info().hash()) + " expected: " + o["lastblockhash"].get_str()); } } } @@ -443,6 +518,7 @@ mArray importUncles(mObject const& blObj, vector& vBiUncles, vector >(expectedAddrs, resultAddrs); + checkAddresses(expectedAddrs, resultAddrs); #endif BOOST_CHECK_MESSAGE(theState.rootHash() == h256(o["postStateRoot"].get_str()), "wrong post state root"); } diff --git a/test/libevm/vm.cpp b/test/libevm/vm.cpp index 2d67d7670..9678f64ff 100644 --- a/test/libevm/vm.cpp +++ b/test/libevm/vm.cpp @@ -492,16 +492,10 @@ BOOST_AUTO_TEST_CASE(vmPerformanceTest) dev::test::executeTests("vmPerformanceTest", "/VMTests",dev::test::getFolder(__FILE__) + "/VMTestsFiller", dev::test::doVMTests); } -BOOST_AUTO_TEST_CASE(vmInputLimitsTest1) +BOOST_AUTO_TEST_CASE(vmInputLimitsTest) { if (test::Options::get().inputLimits) - dev::test::executeTests("vmInputLimits1", "/VMTests",dev::test::getFolder(__FILE__) + "/VMTestsFiller", dev::test::doVMTests); -} - -BOOST_AUTO_TEST_CASE(vmInputLimitsTest2) -{ - if (test::Options::get().inputLimits) - dev::test::executeTests("vmInputLimits2", "/VMTests",dev::test::getFolder(__FILE__) + "/VMTestsFiller", dev::test::doVMTests); + dev::test::executeTests("vmInputLimits", "/VMTests",dev::test::getFolder(__FILE__) + "/VMTestsFiller", dev::test::doVMTests); } BOOST_AUTO_TEST_CASE(vmInputLimitsLightTest) diff --git a/test/libjsengine/CMakeLists.txt b/test/libjsengine/CMakeLists.txt new file mode 100644 index 000000000..3ceda13b0 --- /dev/null +++ b/test/libjsengine/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_policy(SET CMP0015 NEW) + +aux_source_directory(. SRCS) + +add_sources(${SRCS}) diff --git a/test/libjsengine/JSV8Engine.cpp b/test/libjsengine/JSV8Engine.cpp new file mode 100644 index 000000000..da6a0da0e --- /dev/null +++ b/test/libjsengine/JSV8Engine.cpp @@ -0,0 +1,71 @@ +// +// Created by Marek Kotewicz on 27/04/15. +// + +#include +#include +#include + +using namespace std; +using namespace dev; +using namespace dev::eth; + +BOOST_AUTO_TEST_SUITE(jsv8engine) + +BOOST_AUTO_TEST_CASE(evalInteger) +{ + JSV8Engine engine; + JSV8Printer printer(engine); + auto value = engine.eval("1 + 1"); + string result = printer.print(value).cstr(); + BOOST_CHECK_EQUAL(result, "2"); +} + +BOOST_AUTO_TEST_CASE(evalString) +{ + JSV8Engine engine; + JSV8Printer printer(engine); + auto value = engine.eval("'hello ' + 'world'"); + string result = printer.print(value).cstr(); + BOOST_CHECK_EQUAL(result, "hello world"); +} + +BOOST_AUTO_TEST_CASE(evalEmpty) +{ + JSV8Engine engine; + JSV8Printer printer(engine); + auto value = engine.eval(""); + string result = printer.print(value).cstr(); + BOOST_CHECK_EQUAL(result, "undefined"); +} + +BOOST_AUTO_TEST_CASE(evalAssignment) +{ + JSV8Engine engine; + JSV8Printer printer(engine); + auto value = engine.eval("x = 5"); + string result = printer.print(value).cstr(); + BOOST_CHECK_EQUAL(result, "5"); +} + +BOOST_AUTO_TEST_CASE(evalIncorrectExpression) +{ + JSV8Engine engine; + JSV8Printer printer(engine); + auto value = engine.eval("["); + string result = printer.print(value).cstr(); + BOOST_CHECK_EQUAL(result, "Error: Uncaught SyntaxError: Unexpected end of input"); +} + +BOOST_AUTO_TEST_CASE(evalNull) +{ + JSV8Engine engine; + JSV8Printer printer(engine); + auto value = engine.eval("null"); + string result = printer.print(value).cstr(); + string prettyResult = printer.prettyPrint(value).cstr(); + BOOST_CHECK_EQUAL(result, "null"); + BOOST_CHECK_EQUAL(prettyResult.find("null") != std::string::npos, true); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libp2p/net.cpp b/test/libp2p/net.cpp index 9a5dbb32f..a95e685c7 100644 --- a/test/libp2p/net.cpp +++ b/test/libp2p/net.cpp @@ -82,7 +82,7 @@ struct TestNodeTable: public NodeTable bi::address ourIp = bi::address::from_string("127.0.0.1"); for (auto& n: _testNodes) { - ping(bi::udp::endpoint(ourIp, n.second)); + ping(NodeIPEndpoint(ourIp, n.second, n.second)); this_thread::sleep_for(chrono::milliseconds(2)); } } @@ -226,7 +226,7 @@ BOOST_AUTO_TEST_CASE(v2PingNodePacket) PingNode p((bi::udp::endpoint())); BOOST_REQUIRE_NO_THROW(p = PingNode::fromBytesConstRef(bi::udp::endpoint(), bytesConstRef(&s.out()))); - BOOST_REQUIRE(p.version == 2); + BOOST_REQUIRE(p.version == 0); } BOOST_AUTO_TEST_CASE(neighboursPacketLength) @@ -235,8 +235,8 @@ BOOST_AUTO_TEST_CASE(neighboursPacketLength) std::vector> testNodes(TestNodeTable::createTestNodes(16)); bi::udp::endpoint to(boost::asio::ip::address::from_string("127.0.0.1"), 30000); - // hash(32), signature(65), overhead: packet(2), type(1), nodeList(2), ts(9), - static unsigned const nlimit = (1280 - 111) / 87; + // hash(32), signature(65), overhead: packetSz(3), type(1), nodeListSz(3), ts(5), + static unsigned const nlimit = (1280 - 109) / 90; // neighbour: 2 + 65 + 3 + 3 + 17 for (unsigned offset = 0; offset < testNodes.size(); offset += nlimit) { Neighbours out(to); @@ -244,11 +244,9 @@ BOOST_AUTO_TEST_CASE(neighboursPacketLength) auto limit = nlimit ? std::min(testNodes.size(), (size_t)(offset + nlimit)) : testNodes.size(); for (auto i = offset; i < limit; i++) { - Neighbours::Node node; - node.ipAddress = boost::asio::ip::address::from_string("200.200.200.200").to_string(); - node.udpPort = testNodes[i].second; - node.node = testNodes[i].first.pub(); - out.nodes.push_back(node); + Node n(testNodes[i].first.pub(), NodeIPEndpoint(boost::asio::ip::address::from_string("200.200.200.200"), testNodes[i].second, testNodes[i].second)); + Neighbours::Neighbour neighbour(n); + out.neighbours.push_back(neighbour); } out.sign(k.sec()); @@ -256,7 +254,7 @@ BOOST_AUTO_TEST_CASE(neighboursPacketLength) } } -BOOST_AUTO_TEST_CASE(test_neighbours_packet) +BOOST_AUTO_TEST_CASE(neighboursPacket) { KeyPair k = KeyPair::create(); std::vector> testNodes(TestNodeTable::createTestNodes(16)); @@ -265,11 +263,9 @@ BOOST_AUTO_TEST_CASE(test_neighbours_packet) Neighbours out(to); for (auto n: testNodes) { - Neighbours::Node node; - node.ipAddress = boost::asio::ip::address::from_string("127.0.0.1").to_string(); - node.udpPort = n.second; - node.node = n.first.pub(); - out.nodes.push_back(node); + Node node(n.first.pub(), NodeIPEndpoint(boost::asio::ip::address::from_string("200.200.200.200"), n.second, n.second)); + Neighbours::Neighbour neighbour(node); + out.neighbours.push_back(neighbour); } out.sign(k.sec()); @@ -277,9 +273,9 @@ BOOST_AUTO_TEST_CASE(test_neighbours_packet) bytesConstRef rlpBytes(packet.cropped(h256::size + Signature::size + 1)); Neighbours in = Neighbours::fromBytesConstRef(to, rlpBytes); int count = 0; - for (auto n: in.nodes) + for (auto n: in.neighbours) { - BOOST_REQUIRE_EQUAL(testNodes[count].second, n.udpPort); + BOOST_REQUIRE_EQUAL(testNodes[count].second, n.endpoint.udpPort); BOOST_REQUIRE_EQUAL(testNodes[count].first.pub(), n.node); BOOST_REQUIRE_EQUAL(sha3(testNodes[count].first.pub()), sha3(n.node)); count++; @@ -293,12 +289,6 @@ BOOST_AUTO_TEST_CASE(test_findnode_neighbours) // into the same list of nearest nodes. } -BOOST_AUTO_TEST_CASE(test_windows_template) -{ - bi::udp::endpoint ep; - PingNode p(ep); -} - BOOST_AUTO_TEST_CASE(kademlia) { // Not yet a 'real' test. @@ -332,7 +322,7 @@ BOOST_AUTO_TEST_CASE(kademlia) } -BOOST_AUTO_TEST_CASE(test_udp_once) +BOOST_AUTO_TEST_CASE(udpOnce) { UDPDatagram d(bi::udp::endpoint(boost::asio::ip::address::from_string("127.0.0.1"), 30300), bytes({65,65,65,65})); TestUDPSocket a; a.m_socket->connect(); a.start(); diff --git a/test/libp2p/peer.cpp b/test/libp2p/peer.cpp index 2e3320006..192dacd7b 100644 --- a/test/libp2p/peer.cpp +++ b/test/libp2p/peer.cpp @@ -51,6 +51,8 @@ BOOST_AUTO_TEST_CASE(host) auto node2 = host2.id(); host2.start(); + while (!host2.isStarted()) + this_thread::sleep_for(chrono::milliseconds(20)); host1.addNode(node2, NodeIPEndpoint(bi::address::from_string("127.0.0.1"), host2prefs.listenPort, host2prefs.listenPort)); this_thread::sleep_for(chrono::seconds(3)); @@ -72,7 +74,7 @@ BOOST_AUTO_TEST_CASE(networkConfig) BOOST_REQUIRE(save.id() == restore.id()); } -BOOST_AUTO_TEST_CASE(save_nodes) +BOOST_AUTO_TEST_CASE(saveNodes) { std::list hosts; for (auto i:{0,1,2,3,4,5}) @@ -111,8 +113,8 @@ BOOST_AUTO_TEST_CASE(save_nodes) for (auto i: r[2]) { - BOOST_REQUIRE(i.itemCount() == 3 || i.itemCount() == 10); - BOOST_REQUIRE(i[0].itemCount() == 4 || i[0].itemCount() == 16); + BOOST_REQUIRE(i.itemCount() == 4 || i.itemCount() == 11); + BOOST_REQUIRE(i[0].size() == 4 || i[0].size() == 16); } } diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index 26d0110b8..f9bf78d0a 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -525,6 +525,49 @@ BOOST_AUTO_TEST_CASE(constructor_abi) checkInterface(sourceCode, interface); } + +BOOST_AUTO_TEST_CASE(return_param_in_abi) +{ + // bug #1801 + char const* sourceCode = R"( + contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function test(ActionChoices param) {} + function ret() returns(ActionChoices){ + ActionChoices action = ActionChoices.GoLeft; + return action; + } + } + )"; + + char const* interface = R"( + [ + { + "constant" : false, + "inputs" : [], + "name" : "ret", + "outputs" : [ + { + "name" : "", + "type" : "uint8" + } + ], + "type" : "function" + }, + { + "inputs": [ + { + "name": "param", + "type": "uint8" + } + ], + "type": "constructor" + } + ] + )"; + checkInterface(sourceCode, interface); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityCompiler.cpp b/test/libsolidity/SolidityCompiler.cpp index 7b0ceedb6..aa83c4650 100644 --- a/test/libsolidity/SolidityCompiler.cpp +++ b/test/libsolidity/SolidityCompiler.cpp @@ -96,7 +96,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) "}\n"; bytes code = compileContract(sourceCode); - unsigned boilerplateSize = 70; + unsigned boilerplateSize = 73; bytes expectation({byte(Instruction::JUMPDEST), byte(Instruction::PUSH1), 0x0, // initialize local variable x byte(Instruction::PUSH1), 0x2, @@ -114,8 +114,8 @@ BOOST_AUTO_TEST_CASE(ifStatement) " function f() { bool x; if (x) 77; else if (!x) 78; else 79; }" "}\n"; bytes code = compileContract(sourceCode); - unsigned shift = 57; - unsigned boilerplateSize = 70; + unsigned shift = 60; + unsigned boilerplateSize = 73; bytes expectation({byte(Instruction::JUMPDEST), byte(Instruction::PUSH1), 0x0, byte(Instruction::DUP1), @@ -155,8 +155,8 @@ BOOST_AUTO_TEST_CASE(loops) " function f() { while(true){1;break;2;continue;3;return;4;} }" "}\n"; bytes code = compileContract(sourceCode); - unsigned shift = 57; - unsigned boilerplateSize = 70; + unsigned shift = 60; + unsigned boilerplateSize = 73; bytes expectation({byte(Instruction::JUMPDEST), byte(Instruction::JUMPDEST), byte(Instruction::PUSH1), 0x1, diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index f168ad454..ed5f1acdf 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -2962,12 +2962,13 @@ BOOST_AUTO_TEST_CASE(bytes_in_arguments) } )"; compileAndRun(sourceCode); + string innercalldata1 = asString(FixedHash<4>(dev::sha3("f(uint256,uint256)")).asBytes() + encodeArgs(8, 9)); - bytes calldata1 = encodeArgs(u256(innercalldata1.length()), 12, innercalldata1, 13); string innercalldata2 = asString(FixedHash<4>(dev::sha3("g(uint256)")).asBytes() + encodeArgs(3)); bytes calldata = encodeArgs( - 12, u256(innercalldata1.length()), u256(innercalldata2.length()), 13, - innercalldata1, innercalldata2); + 12, 32 * 4, u256(32 * 4 + 32 + (innercalldata1.length() + 31) / 32 * 32), 13, + u256(innercalldata1.length()), innercalldata1, + u256(innercalldata2.length()), innercalldata2); BOOST_CHECK(callContractFunction("test(uint256,bytes,bytes,uint256)", calldata) == encodeArgs(12, (8 + 9) * 3, 13, u256(innercalldata1.length()))); } @@ -3383,9 +3384,10 @@ BOOST_AUTO_TEST_CASE(external_array_args) compileAndRun(sourceCode); bytes params = encodeArgs( 1, 2, 3, 4, 5, 6, 7, 8, // a - 3, // b.length + 32 * (8 + 1 + 5 + 1 + 1 + 1), // offset to b 21, 22, 23, 24, 25, // c 0, 1, 2, // (a,b,c)_index + 3, // b.length 11, 12, 13 // b ); BOOST_CHECK(callContractFunction("test(uint256[8],uint256[],uint256[5],uint256,uint256,uint256)", params) == encodeArgs(1, 12, 23)); @@ -3422,8 +3424,8 @@ BOOST_AUTO_TEST_CASE(bytes_index_access) 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33}; - BOOST_CHECK(callContractFunction("direct(bytes,uint256)", u256(array.length()), 32, array) == encodeArgs(32)); - BOOST_CHECK(callContractFunction("storageCopyRead(bytes,uint256)", u256(array.length()), 32, array) == encodeArgs(32)); + BOOST_CHECK(callContractFunction("direct(bytes,uint256)", 64, 33, u256(array.length()), array) == encodeArgs(33)); + BOOST_CHECK(callContractFunction("storageCopyRead(bytes,uint256)", 64, 33, u256(array.length()), array) == encodeArgs(33)); BOOST_CHECK(callContractFunction("storageWrite()") == encodeArgs(0x193)); } @@ -3474,6 +3476,7 @@ BOOST_AUTO_TEST_CASE(array_copy_calldata_storage) compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("store(uint256[9],uint8[3][])", encodeArgs( 21, 22, 23, 24, 25, 26, 27, 28, 29, // a + u256(32 * (9 + 1)), 4, // size of b 1, 2, 3, // b[0] 11, 12, 13, // b[1] @@ -3502,7 +3505,7 @@ BOOST_AUTO_TEST_CASE(array_copy_nested_array) )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("test(uint256[2][])", encodeArgs( - 3, + 32, 3, 7, 8, 9, 10, 11, 12 @@ -3910,6 +3913,90 @@ BOOST_AUTO_TEST_CASE(external_types_in_calls) BOOST_CHECK(callContractFunction("nonexisting") == encodeArgs(u256(9))); } +BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes) +{ + // bug #1798 + char const* sourceCode = R"( + contract init { + function isOk() returns (bool) { return false; } + bool public ok = false; + } + contract fix { + function isOk() returns (bool) { return true; } + bool public ok = true; + } + + contract init_fix is init, fix { + function checkOk() returns (bool) { return ok; } + } + contract fix_init is fix, init { + function checkOk() returns (bool) { return ok; } + } + )"; + compileAndRun(sourceCode, 0, "init_fix"); + BOOST_CHECK(callContractFunction("isOk()") == encodeArgs(true)); + BOOST_CHECK(callContractFunction("ok()") == encodeArgs(true)); + + compileAndRun(sourceCode, 0, "fix_init"); + BOOST_CHECK(callContractFunction("isOk()") == encodeArgs(false)); + BOOST_CHECK(callContractFunction("ok()") == encodeArgs(false)); +} + +BOOST_AUTO_TEST_CASE(proper_overwriting_accessor_by_function) +{ + // bug #1798 + char const* sourceCode = R"( + contract attribute { + bool ok = false; + } + contract func { + function ok() returns (bool) { return true; } + } + + contract attr_func is attribute, func { + function checkOk() returns (bool) { return ok(); } + } + contract func_attr is func, attribute { + function checkOk() returns (bool) { return ok; } + } + )"; + compileAndRun(sourceCode, 0, "attr_func"); + BOOST_CHECK(callContractFunction("ok()") == encodeArgs(true)); + compileAndRun(sourceCode, 0, "func_attr"); + BOOST_CHECK(callContractFunction("checkOk()") == encodeArgs(false)); +} + + +BOOST_AUTO_TEST_CASE(overwriting_inheritance) +{ + // bug #1798 + char const* sourceCode = R"( + contract A { + function ok() returns (uint) { return 1; } + } + contract B { + function ok() returns (uint) { return 2; } + } + contract C { + uint ok = 6; + } + contract AB is A, B { + function ok() returns (uint) { return 4; } + } + contract reversedE is C, AB { + function checkOk() returns (uint) { return ok(); } + } + contract E is AB, C { + function checkOk() returns (uint) { return ok; } + } + )"; + compileAndRun(sourceCode, 0, "reversedE"); + BOOST_CHECK(callContractFunction("checkOk()") == encodeArgs(4)); + compileAndRun(sourceCode, 0, "E"); + BOOST_CHECK(callContractFunction("checkOk()") == encodeArgs(6)); +} + + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index c317dad97..4ec7b8bda 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -508,6 +508,28 @@ BOOST_AUTO_TEST_CASE(function_external_types) } } +BOOST_AUTO_TEST_CASE(enum_external_type) +{ + // bug #1801 + ASTPointer sourceUnit; + char const* text = R"( + contract Test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function boo(ActionChoices enumArg) external returns (uint ret) { + ret = 5; + } + })"; + ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseTextAndResolveNames(text), "Parsing and name Resolving failed"); + for (ASTPointer const& node: sourceUnit->getNodes()) + if (ContractDefinition* contract = dynamic_cast(node.get())) + { + auto functions = contract->getDefinedFunctions(); + if (functions.empty()) + continue; + BOOST_CHECK_EQUAL("boo(uint8)", functions[0]->externalSignature()); + } +} + BOOST_AUTO_TEST_CASE(function_external_call_allowed_conversion) { char const* text = R"( diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 9cdaa5886..3cb6a536a 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -83,14 +83,28 @@ public: "\nOptimized: " + toHex(optimizedOutput)); } - AssemblyItems getCSE(AssemblyItems const& _input) + AssemblyItems addDummyLocations(AssemblyItems const& _input) { // add dummy locations to each item so that we can check that they are not deleted AssemblyItems input = _input; for (AssemblyItem& item: input) item.setLocation(SourceLocation(1, 3, make_shared(""))); + return input; + } + + eth::KnownState createInitialState(AssemblyItems const& _input) + { + eth::KnownState state; + for (auto const& item: addDummyLocations(_input)) + state.feedItem(item); + return state; + } + + AssemblyItems getCSE(AssemblyItems const& _input, eth::KnownState const& _state = eth::KnownState()) + { + AssemblyItems input = addDummyLocations(_input); - eth::CommonSubexpressionEliminator cse; + eth::CommonSubexpressionEliminator cse(_state); BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); AssemblyItems output = cse.getOptimizedItems(); @@ -101,9 +115,13 @@ public: return output; } - void checkCSE(AssemblyItems const& _input, AssemblyItems const& _expectation) + void checkCSE( + AssemblyItems const& _input, + AssemblyItems const& _expectation, + KnownState const& _state = eth::KnownState() + ) { - AssemblyItems output = getCSE(_input); + AssemblyItems output = getCSE(_input, _state); BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end()); } @@ -113,8 +131,12 @@ public: // Running it four times should be enough for these tests. for (unsigned i = 0; i < 4; ++i) { - eth::ControlFlowGraph cfg(output); - output = cfg.optimisedItems(); + ControlFlowGraph cfg(output); + AssemblyItems optItems; + for (BasicBlock const& block: cfg.optimisedBlocks()) + copy(output.begin() + block.begin, output.begin() + block.end, + back_inserter(optItems)); + output = move(optItems); } BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end()); } @@ -231,7 +253,8 @@ BOOST_AUTO_TEST_CASE(function_calls) BOOST_AUTO_TEST_CASE(cse_intermediate_swap) { - eth::CommonSubexpressionEliminator cse; + eth::KnownState state; + eth::CommonSubexpressionEliminator cse(state); AssemblyItems input{ Instruction::SWAP1, Instruction::POP, Instruction::ADD, u256(0), Instruction::SWAP1, Instruction::SLOAD, Instruction::SWAP1, u256(100), Instruction::EXP, Instruction::SWAP1, @@ -754,6 +777,30 @@ BOOST_AUTO_TEST_CASE(cse_sha3_twice_same_content_noninterfering_store_in_between BOOST_CHECK_EQUAL(1, count(output.begin(), output.end(), AssemblyItem(Instruction::SHA3))); } +BOOST_AUTO_TEST_CASE(cse_with_initially_known_stack) +{ + eth::KnownState state = createInitialState(AssemblyItems{ + u256(0x12), + u256(0x20), + Instruction::ADD + }); + AssemblyItems input{ + u256(0x12 + 0x20) + }; + checkCSE(input, AssemblyItems{Instruction::DUP1}, state); +} + +BOOST_AUTO_TEST_CASE(cse_equality_on_initially_known_stack) +{ + eth::KnownState state = createInitialState(AssemblyItems{Instruction::DUP1}); + AssemblyItems input{ + Instruction::EQ + }; + AssemblyItems output = getCSE(input, state); + // check that it directly pushes 1 (true) + BOOST_CHECK(find(output.begin(), output.end(), AssemblyItem(u256(1))) != output.end()); +} + BOOST_AUTO_TEST_CASE(control_flow_graph_remove_unused) { // remove parts of the code that are unused diff --git a/test/libweb3jsonrpc/AccountHolder.cpp b/test/libweb3jsonrpc/AccountHolder.cpp index e8e42ff18..c9500a6ef 100644 --- a/test/libweb3jsonrpc/AccountHolder.cpp +++ b/test/libweb3jsonrpc/AccountHolder.cpp @@ -22,6 +22,9 @@ #include #include +using namespace std; +using namespace dev; +using namespace eth; namespace dev { @@ -32,16 +35,17 @@ BOOST_AUTO_TEST_SUITE(AccountHolderTest) BOOST_AUTO_TEST_CASE(ProxyAccountUseCase) { - AccountHolder h = AccountHolder(std::function()); - BOOST_CHECK(h.getAllAccounts().empty()); - BOOST_CHECK(h.getRealAccounts().empty()); + FixedAccountHolder h = FixedAccountHolder(function(), vector()); + + BOOST_CHECK(h.allAccounts().empty()); + BOOST_CHECK(h.realAccounts().empty()); Address addr("abababababababababababababababababababab"); Address addr2("abababababababababababababababababababab"); int id = h.addProxyAccount(addr); - BOOST_CHECK(h.getQueuedTransactions(id).empty()); + BOOST_CHECK(h.queuedTransactions(id).empty()); // register it again int secondID = h.addProxyAccount(addr); - BOOST_CHECK(h.getQueuedTransactions(secondID).empty()); + BOOST_CHECK(h.queuedTransactions(secondID).empty()); eth::TransactionSkeleton t1; eth::TransactionSkeleton t2; @@ -49,20 +53,20 @@ BOOST_AUTO_TEST_CASE(ProxyAccountUseCase) t1.data = fromHex("12345678"); t2.from = addr; t2.data = fromHex("abcdef"); - BOOST_CHECK(h.getQueuedTransactions(id).empty()); + BOOST_CHECK(h.queuedTransactions(id).empty()); h.queueTransaction(t1); - BOOST_CHECK_EQUAL(1, h.getQueuedTransactions(id).size()); + BOOST_CHECK_EQUAL(1, h.queuedTransactions(id).size()); h.queueTransaction(t2); - BOOST_REQUIRE_EQUAL(2, h.getQueuedTransactions(id).size()); + BOOST_REQUIRE_EQUAL(2, h.queuedTransactions(id).size()); // second proxy should not see transactions - BOOST_CHECK(h.getQueuedTransactions(secondID).empty()); + BOOST_CHECK(h.queuedTransactions(secondID).empty()); - BOOST_CHECK(h.getQueuedTransactions(id)[0].data == t1.data); - BOOST_CHECK(h.getQueuedTransactions(id)[1].data == t2.data); + BOOST_CHECK(h.queuedTransactions(id)[0].data == t1.data); + BOOST_CHECK(h.queuedTransactions(id)[1].data == t2.data); h.clearQueue(id); - BOOST_CHECK(h.getQueuedTransactions(id).empty()); + BOOST_CHECK(h.queuedTransactions(id).empty()); // removing fails because it never existed BOOST_CHECK(!h.removeProxyAccount(secondID)); BOOST_CHECK(h.removeProxyAccount(id));