From 40cf37dbb8ba6b5a4162f0c61e283a01cb0871df Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 8 May 2015 10:31:10 +0200 Subject: [PATCH 001/157] - basic transaction creation. --- mix/ClientModel.cpp | 36 +++++++++++++++------ mix/ClientModel.h | 11 ++++--- mix/qml/QAddressView.qml | 57 +++++++++++++++++++++++++++++++++ mix/qml/StateListModel.qml | 8 +++-- mix/qml/StructView.qml | 29 ++--------------- mix/qml/TransactionDialog.qml | 55 +++++++++++++++++++++++++++++++ mix/qml/js/TransactionHelper.js | 3 +- 7 files changed, 156 insertions(+), 43 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 717757c70..7f4817c91 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -250,7 +250,10 @@ void ClientModel::setupState(QVariantMap _state) u256 value = (qvariant_cast(transaction.value("value")))->toU256Wei(); u256 gasPrice = (qvariant_cast(transaction.value("gasPrice")))->toU256Wei(); QString sender = transaction.value("sender").toString(); - bool isStdContract = (transaction.value("stdContract").toBool()); + bool isStdContract = transaction.value("stdContract").toBool(); + bool isContractCall; + if (!transaction.value("isContractCall").isNull()) + isContractCall = transaction.value("isContractCall").toBool(); if (isStdContract) { if (contractId.isEmpty()) //TODO: This is to support old project files, remove later @@ -266,7 +269,7 @@ void ClientModel::setupState(QVariantMap _state) { if (contractId.isEmpty() && m_codeModel->hasContract()) //TODO: This is to support old project files, remove later contractId = m_codeModel->contracts().keys()[0]; - TransactionSettings transactionSettings(contractId, functionId, value, gas, gasAuto, gasPrice, Secret(sender.toStdString())); + TransactionSettings transactionSettings(contractId, functionId, value, gas, gasAuto, gasPrice, Secret(sender.toStdString()), isContractCall); transactionSettings.parameterValues = transaction.value("parameters").toMap(); if (contractId == functionId || functionId == "Constructor") @@ -301,6 +304,13 @@ void ClientModel::executeSequence(vector const& _sequence, onStateReset(); for (TransactionSettings const& transaction: _sequence) { + if (!transaction.isContractCall) + { + QString address = resolveToken(transaction.contractId, deployedContracts); + callAddress(Address(address.toStdString()), bytes(), transaction); + onNewTransaction(); + continue; + } ContractCallDataEncoder encoder; if (!transaction.stdContractUrl.isEmpty()) { @@ -342,11 +352,8 @@ void ClientModel::executeSequence(vector const& _sequence, { QSolidityType const* type = p->type(); QVariant value = transaction.parameterValues.value(p->name()); - if (type->type().type == SolidityType::Type::Address && value.toString().startsWith("<") && value.toString().endsWith(">")) - { - QStringList nb = value.toString().remove("<").remove(">").split(" - "); - value = QVariant(QString::fromStdString("0x" + toHex(deployedContracts.at(nb.back().toInt()).ref()))); - } + if (type->type().type == SolidityType::Type::Address) + value = QVariant(resolveToken(value.toString(), deployedContracts)); encoder.encode(value, type->type()); } @@ -376,7 +383,7 @@ void ClientModel::executeSequence(vector const& _sequence, emit runStateChanged(); return; } - callContract(contractAddressIter->second, encoder.encodedData(), transaction); + callAddress(contractAddressIter->second, encoder.encodedData(), transaction); } } onNewTransaction(); @@ -399,6 +406,17 @@ void ClientModel::executeSequence(vector const& _sequence, }); } +QString ClientModel::resolveToken(QString const& _value, vector
const& _contracts) +{ + QString ret = _value; + if (_value.startsWith("<") && _value.endsWith(">")) + { + QStringList nb = ret.remove("<").remove(">").split(" - "); + ret = QString::fromStdString("0x" + toHex(_contracts.at(nb.back().toInt()).ref())); + } + return ret; +} + void ClientModel::showDebugger() { ExecutionResult last = m_client->lastExecution(); @@ -603,7 +621,7 @@ Address ClientModel::deployContract(bytes const& _code, TransactionSettings cons return newAddress; } -void ClientModel::callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr) +void ClientModel::callAddress(Address const& _contract, bytes const& _data, TransactionSettings const& _tr) { m_client->submitTransaction(_tr.sender, _tr.value, _contract, _data, _tr.gas, _tr.gasPrice, _tr.gasAuto); } diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 9b0529ae6..db11406d6 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -53,10 +53,10 @@ struct SolidityType; struct TransactionSettings { TransactionSettings() {} - TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, bool _gasAuto, u256 _gasPrice, Secret _sender): - contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasAuto(_gasAuto), gasPrice(_gasPrice), sender(_sender) {} + TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, bool _gasAuto, u256 _gasPrice, Secret _sender, int _isContractCall): + contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasAuto(_gasAuto), gasPrice(_gasPrice), sender(_sender), isContractCall(_isContractCall) {} TransactionSettings(QString const& _stdContractName, QString const& _stdContractUrl): - contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl) {} + contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl), isContractCall(true) {} /// Contract name QString contractId; @@ -76,6 +76,8 @@ struct TransactionSettings QString stdContractUrl; /// Sender Secret sender; + /// Is a call to a contract + bool isContractCall; }; @@ -220,12 +222,13 @@ private: QVariantMap gasCosts() const; void executeSequence(std::vector const& _sequence, std::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 callAddress(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); + QString resolveToken(QString const& _value, std::vector
const& _contracts); std::atomic m_running; std::atomic m_mining; diff --git a/mix/qml/QAddressView.qml b/mix/qml/QAddressView.qml index 204e92508..19d98b166 100644 --- a/mix/qml/QAddressView.qml +++ b/mix/qml/QAddressView.qml @@ -8,6 +8,10 @@ Item property alias accountRef: ctrModel property string subType property bool readOnly + property alias currentIndex: trCombobox.currentIndex + property alias currentText: textinput.text + property variant accounts + signal indexChanged() id: editRoot height: 20 width: 320 @@ -17,6 +21,46 @@ Item id: boldFont } + function currentValue() { + return currentText; + } + + function currentType() + { + return accountRef.get(trCombobox.currentIndex).type; + } + + function load() + { + accountRef.clear(); + accountRef.append({"itemid": " - "}); + + if (subType === "contract" || subType === "address") + { + var trCr = 0; + for (var k = 0; k < transactionsModel.count; k++) + { + if (k >= transactionIndex) + break; + var tr = transactionsModel.get(k); + if (tr.functionId === tr.contractId /*&& (dec[1] === tr.contractId || item.subType === "address")*/) + { + accountRef.append({ "itemid": tr.contractId + " - " + trCr, "value": "<" + tr.contractId + " - " + trCr + ">", "type": "contract" }); + trCr++; + } + } + } + if (subType === "address") + { + for (k = 0; k < accounts.length; k++) + { + if (accounts[k].address === undefined) + accounts[k].address = clientModel.address(accounts[k].secret); + accountRef.append({ "itemid": accounts[k].name, "value": "0x" + accounts[k].address, "type": "address" }); + } + } + } + function init() { trCombobox.visible = !readOnly @@ -35,6 +79,18 @@ Item } } + function select(address) + { + for (var k = 0; k < accountRef.count; k++) + { + if (accountRef.get(k).value === address) + { + trCombobox.currentIndex = k; + break; + } + } + } + Rectangle { anchors.fill: parent radius: 4 @@ -96,6 +152,7 @@ Item { textinput.text = ""; } + indexChanged(); } } } diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index 889a2d940..d4aa678a6 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -46,6 +46,7 @@ Item { t.sender = defaultAccount; //support for old project var r = { + type: t.type, contractId: t.contractId, functionId: t.functionId, url: t.url, @@ -55,7 +56,8 @@ Item { gasAuto: t.gasAuto, stdContract: t.stdContract ? true : false, parameters: {}, - sender: t.sender + sender: t.sender, + isContractCall: t.isContractCall }; for (var key in t.parameters) r.parameters[key] = t.parameters[key]; @@ -100,6 +102,7 @@ Item { function toPlainTransactionItem(t) { var r = { + type: t.type, contractId: t.contractId, functionId: t.functionId, url: t.url, @@ -109,7 +112,8 @@ Item { gasPrice: { value: t.gasPrice.value, unit: t.gasPrice.unit }, stdContract: t.stdContract, sender: t.sender, - parameters: {} + parameters: {}, + isContractCall: t.isContractCall }; for (var key in t.parameters) r.parameters[key] = t.parameters[key]; diff --git a/mix/qml/StructView.qml b/mix/qml/StructView.qml index 4df9ace67..4feab2166 100644 --- a/mix/qml/StructView.qml +++ b/mix/qml/StructView.qml @@ -75,38 +75,13 @@ Column item.readOnly = context === "variable"; if (ptype.category === QSolidityType.Address) { + item.accounts = accounts item.value = getValue(); if (context === "parameter") { var dec = modelData.type.name.split(" "); item.subType = dec[0]; - item.accountRef.append({"itemid": " - "}); - - if (item.subType === "contract" || item.subType === "address") - { - var trCr = 0; - for (var k = 0; k < transactionsModel.count; k++) - { - if (k >= transactionIndex) - break; - var tr = transactionsModel.get(k); - if (tr.functionId === tr.contractId && (dec[1] === tr.contractId || item.subType === "address")) - { - item.accountRef.append({ "itemid": tr.contractId + " - " + trCr, "value": "<" + tr.contractId + " - " + trCr + ">", "type": "contract" }); - trCr++; - } - } - } - if (item.subType === "address") - { - for (k = 0; k < accounts.length; k++) - { - if (accounts[k].address === undefined) - accounts[k].address = clientModel.address(accounts[k].secret); - item.accountRef.append({ "itemid": accounts[k].name, "value": "0x" + accounts[k].address, "type": "address" }); - } - - } + item.load(); } item.init(); } diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 66a98d19e..f56093336 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -82,6 +82,14 @@ Dialog { } initTypeLoader(); + trType.checked = item.isContractCall + trType.init(); + + recipients.accounts = senderComboBox.model; + recipients.subType = "address"; + recipients.load(); + recipients.init(); + recipients.select(contractId); visible = true; valueField.focus = true; } @@ -193,6 +201,13 @@ Dialog { item.functionId = transactionDialog.functionId; } + item.isContractCall = trType.checked; + if (!item.isContractCall) + { + item.functionId = recipients.currentText; + item.contractId = recipients.currentText; + } + item.sender = senderComboBox.model[senderComboBox.currentIndex].secret; item.parameters = paramValues; return item; @@ -238,6 +253,46 @@ Dialog { } } + RowLayout + { + id: rowIsContract + Layout.fillWidth: true + height: 150 + CheckBox { + id: trType + onCheckedChanged: + { + init(); + } + + function init() + { + rowFunction.visible = checked; + rowContract.visible = checked; + rowRecipient.visible = !checked; + } + + text: qsTr("is contract call") + checked: true + } + } + + RowLayout + { + id: rowRecipient + Layout.fillWidth: true + height: 150 + DefaultLabel { + Layout.preferredWidth: 75 + text: qsTr("Recipient") + } + + QAddressView + { + id: recipients + } + } + RowLayout { id: rowContract diff --git a/mix/qml/js/TransactionHelper.js b/mix/qml/js/TransactionHelper.js index be057917c..57b03757a 100644 --- a/mix/qml/js/TransactionHelper.js +++ b/mix/qml/js/TransactionHelper.js @@ -9,7 +9,8 @@ function defaultTransaction() gasAuto: true, gasPrice: createEther("100000", QEther.Wei), parameters: {}, - stdContract: false + stdContract: false, + isContractCall: true }; } From 446abc57e55b3d6ba70875a06fd09b7964ecc7fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 8 May 2015 11:00:17 +0200 Subject: [PATCH 002/157] testeth: fix --singletest option --- test/TestHelper.cpp | 89 +++++++++++++++----------------- test/TestHelper.h | 3 +- test/libethereum/blockchain.cpp | 2 +- test/libethereum/state.cpp | 2 +- test/libethereum/transaction.cpp | 2 +- test/libevm/vm.cpp | 2 +- 6 files changed, 47 insertions(+), 53 deletions(-) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 144a1a286..e0aad310f 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -549,58 +549,50 @@ void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _e } } -void userDefinedTest(string testTypeFlag, std::function doTests) +void userDefinedTest(std::function doTests) { - Options::get(); // parse command line options, e.g. to enable JIT + if (!Options::get().singleTest) + { + cnote << "Missing user test specification\nUsage: testeth --singletest \n"; + return; + } - for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) + auto& filename = Options::get().singleTestFile; + auto& testname = Options::get().singleTestName; + int currentVerbosity = g_logVerbosity; + g_logVerbosity = 12; + try { - string arg = boost::unit_test::framework::master_test_suite().argv[i]; - if (arg == testTypeFlag) - { - if (boost::unit_test::framework::master_test_suite().argc <= i + 2) - { - cnote << "Missing filename\nUsage: testeth " << testTypeFlag << " \n"; - return; - } - string filename = boost::unit_test::framework::master_test_suite().argv[i + 1]; - string testname = boost::unit_test::framework::master_test_suite().argv[i + 2]; - int currentVerbosity = g_logVerbosity; - g_logVerbosity = 12; - try - { - cnote << "Testing user defined test: " << filename; - json_spirit::mValue v; - string s = asString(contents(filename)); - BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + filename + " is empty. "); - json_spirit::read_string(s, v); - json_spirit::mObject oSingleTest; - - json_spirit::mObject::const_iterator pos = v.get_obj().find(testname); - if (pos == v.get_obj().end()) - { - cnote << "Could not find test: " << testname << " in " << filename << "\n"; - return; - } - else - oSingleTest[pos->first] = pos->second; + cnote << "Testing user defined test: " << filename; + json_spirit::mValue v; + string s = asString(contents(filename)); + BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + filename + " is empty. "); + json_spirit::read_string(s, v); + json_spirit::mObject oSingleTest; - json_spirit::mValue v_singleTest(oSingleTest); - doTests(v_singleTest, false); - } - catch (Exception const& _e) - { - BOOST_ERROR("Failed Test with Exception: " << diagnostic_information(_e)); - g_logVerbosity = currentVerbosity; - } - catch (std::exception const& _e) - { - BOOST_ERROR("Failed Test with Exception: " << _e.what()); - g_logVerbosity = currentVerbosity; - } - g_logVerbosity = currentVerbosity; + json_spirit::mObject::const_iterator pos = v.get_obj().find(testname); + if (pos == v.get_obj().end()) + { + cnote << "Could not find test: " << testname << " in " << filename << "\n"; + return; } + else + oSingleTest[pos->first] = pos->second; + + json_spirit::mValue v_singleTest(oSingleTest); + doTests(v_singleTest, false); + } + catch (Exception const& _e) + { + BOOST_ERROR("Failed Test with Exception: " << diagnostic_information(_e)); + g_logVerbosity = currentVerbosity; + } + catch (std::exception const& _e) + { + BOOST_ERROR("Failed Test with Exception: " << _e.what()); + g_logVerbosity = currentVerbosity; } + g_logVerbosity = currentVerbosity; } void executeTests(const string& _name, const string& _testPathAppendix, const boost::filesystem::path _pathToFiller, std::function doTests) @@ -740,10 +732,11 @@ Options::Options() inputLimits = true; bigData = true; } - else if (arg == "--singletest" && i + 1 < argc) + else if (arg == "--singletest" && i + 2 < argc) { singleTest = true; - singleTestName = argv[i + 1]; + singleTestFile = argv[i + 1]; + singleTestName = argv[i + 2]; } } } diff --git a/test/TestHelper.h b/test/TestHelper.h index 02f509e4c..631bc4df2 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -157,7 +157,7 @@ void checkLog(eth::LogEntries _resultLogs, eth::LogEntries _expectedLogs); void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _expectedCallCreates); void executeTests(const std::string& _name, const std::string& _testPathAppendix, const boost::filesystem::path _pathToFiller, std::function doTests); -void userDefinedTest(std::string testTypeFlag, std::function doTests); +void userDefinedTest(std::function doTests); RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject& _tObj); eth::LastHashes lastHashes(u256 _currentBlockNumber); json_spirit::mObject fillJsonWithState(eth::State _state); @@ -189,6 +189,7 @@ public: /// Test selection /// @{ bool singleTest = false; + std::string singleTestFile; std::string singleTestName; bool performance = false; bool quadratic = false; diff --git a/test/libethereum/blockchain.cpp b/test/libethereum/blockchain.cpp index 954e65c8a..9eddb4657 100644 --- a/test/libethereum/blockchain.cpp +++ b/test/libethereum/blockchain.cpp @@ -711,7 +711,7 @@ BOOST_AUTO_TEST_CASE(bcWalletTest) BOOST_AUTO_TEST_CASE(userDefinedFile) { - dev::test::userDefinedTest("--singletest", dev::test::doBlockchainTests); + dev::test::userDefinedTest(dev::test::doBlockchainTests); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libethereum/state.cpp b/test/libethereum/state.cpp index 93f7498b8..b7b45f93a 100644 --- a/test/libethereum/state.cpp +++ b/test/libethereum/state.cpp @@ -265,7 +265,7 @@ BOOST_AUTO_TEST_CASE(stRandom) BOOST_AUTO_TEST_CASE(userDefinedFileState) { - dev::test::userDefinedTest("--singletest", dev::test::doStateTests); + dev::test::userDefinedTest(dev::test::doStateTests); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libethereum/transaction.cpp b/test/libethereum/transaction.cpp index 058d03322..017e51ded 100644 --- a/test/libethereum/transaction.cpp +++ b/test/libethereum/transaction.cpp @@ -195,7 +195,7 @@ BOOST_AUTO_TEST_CASE(ttCreateTest) BOOST_AUTO_TEST_CASE(userDefinedFile) { - dev::test::userDefinedTest("--singletest", dev::test::doTransactionTests); + dev::test::userDefinedTest(dev::test::doTransactionTests); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libevm/vm.cpp b/test/libevm/vm.cpp index 8b5a7c5d3..2d67d7670 100644 --- a/test/libevm/vm.cpp +++ b/test/libevm/vm.cpp @@ -548,7 +548,7 @@ BOOST_AUTO_TEST_CASE(vmRandom) BOOST_AUTO_TEST_CASE(userDefinedFile) { - dev::test::userDefinedTest("--singletest", dev::test::doVMTests); + dev::test::userDefinedTest(dev::test::doVMTests); } BOOST_AUTO_TEST_SUITE_END() From 5fe68b07c1236c64f58fa7b42bcfb6cc6506e957 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 8 May 2015 14:14:27 +0200 Subject: [PATCH 003/157] small changes --- mix/ClientModel.cpp | 2 +- mix/qml/StateListModel.qml | 2 ++ mix/qml/TransactionDialog.qml | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index d802d9a7b..95d4d497b 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -418,7 +418,7 @@ QString ClientModel::resolveToken(QString const& _value, vector
const& if (_value.startsWith("<") && _value.endsWith(">")) { QStringList nb = ret.remove("<").remove(">").split(" - "); - ret = QString::fromStdString("0x" + toHex(_contracts.at(nb.back().toInt()).ref())); + ret = QString::fromStdString("0x" + dev::toHex(_contracts.at(nb.back().toInt()).ref())); } return ret; } diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index d4aa678a6..3eac14a11 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -59,6 +59,8 @@ Item { sender: t.sender, isContractCall: t.isContractCall }; + if (r.isContractCall === undefined) + r.isContractCall = true; //support for old project for (var key in t.parameters) r.parameters[key] = t.parameters[key]; diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index f56093336..84abb854b 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -270,6 +270,8 @@ Dialog { rowFunction.visible = checked; rowContract.visible = checked; rowRecipient.visible = !checked; + paramLabel.visible = checked; + paramScroll.visible = checked; } text: qsTr("is contract call") From 7802a9e00cca9070a7d20f8157611cfed26c2ecb Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 8 May 2015 17:27:15 +0200 Subject: [PATCH 004/157] bug fix --- mix/ClientModel.cpp | 36 ++++++++----- mix/ClientModel.h | 11 ++-- mix/qml/QAddressView.qml | 5 ++ mix/qml/StateDialog.qml | 4 +- mix/qml/StateListModel.qml | 14 +++-- mix/qml/TransactionDialog.qml | 92 +++++++++++++++++++++++---------- mix/qml/js/TransactionHelper.js | 3 +- 7 files changed, 112 insertions(+), 53 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 95d4d497b..a58366046 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -256,9 +256,9 @@ void ClientModel::setupState(QVariantMap _state) u256 gasPrice = (qvariant_cast(transaction.value("gasPrice")))->toU256Wei(); QString sender = transaction.value("sender").toString(); bool isStdContract = transaction.value("stdContract").toBool(); - bool isContractCall; - if (!transaction.value("isContractCall").isNull()) - isContractCall = transaction.value("isContractCall").toBool(); + bool isContractCreation; + if (!transaction.value("isContractCreation").isNull()) + isContractCreation = transaction.value("isContractCreation").toBool(); if (isStdContract) { if (contractId.isEmpty()) //TODO: This is to support old project files, remove later @@ -274,7 +274,7 @@ void ClientModel::setupState(QVariantMap _state) { if (contractId.isEmpty() && m_codeModel->hasContract()) //TODO: This is to support old project files, remove later contractId = m_codeModel->contracts().keys()[0]; - TransactionSettings transactionSettings(contractId, functionId, value, gas, gasAuto, gasPrice, Secret(sender.toStdString()), isContractCall); + TransactionSettings transactionSettings(contractId, functionId, value, gas, gasAuto, gasPrice, Secret(sender.toStdString()), isContractCreation); transactionSettings.parameterValues = transaction.value("parameters").toMap(); if (contractId == functionId || functionId == "Constructor") @@ -310,9 +310,10 @@ void ClientModel::executeSequence(vector const& _sequence, m_gasCosts.clear(); for (TransactionSettings const& transaction: _sequence) { - if (!transaction.isContractCall) + QString contractName = resolveContractName(transaction.contractId); + QString address = resolveToken(transaction.contractId, deployedContracts); + if (transaction.functionId == "(transfert)") { - QString address = resolveToken(transaction.contractId, deployedContracts); callAddress(Address(address.toStdString()), bytes(), transaction); onNewTransaction(); continue; @@ -332,7 +333,7 @@ void ClientModel::executeSequence(vector const& _sequence, else { //encode data - CompiledContract const& compilerRes = m_codeModel->contract(transaction.contractId); + CompiledContract const& compilerRes = m_codeModel->contract(contractName); QFunctionDefinition const* f = nullptr; bytes contractCode = compilerRes.bytes(); shared_ptr contractDef = compilerRes.sharedContract(); @@ -363,7 +364,7 @@ void ClientModel::executeSequence(vector const& _sequence, encoder.encode(value, type->type()); } - if (transaction.functionId.isEmpty() || transaction.functionId == transaction.contractId) + if (transaction.functionId.isEmpty() || transaction.functionId == contractName) { bytes param = encoder.encodedData(); contractCode.insert(contractCode.end(), param.begin(), param.end()); @@ -372,8 +373,9 @@ void ClientModel::executeSequence(vector const& _sequence, auto contractAddressIter = m_contractAddresses.find(transaction.contractId); if (contractAddressIter == m_contractAddresses.end() || newAddress != contractAddressIter->second) { - m_contractAddresses[transaction.contractId] = newAddress; - m_contractNames[newAddress] = transaction.contractId; + QString contractToken = "<" + transaction.contractId + " - " + QString::number(deployedContracts.size() - 1) + ">"; + m_contractAddresses[contractToken] = newAddress; + m_contractNames[newAddress] = contractToken; contractAddressesChanged(); } gasCostsChanged(); @@ -388,7 +390,7 @@ void ClientModel::executeSequence(vector const& _sequence, emit runStateChanged(); return; } - callAddress(contractAddressIter->second, encoder.encodedData(), transaction); + callAddress(Address(address.toStdString()), encoder.encodedData(), transaction); } m_gasCosts.append(m_client->lastExecution().gasUsed); } @@ -423,6 +425,14 @@ QString ClientModel::resolveToken(QString const& _value, vector
const& return ret; } +QString ClientModel::resolveContractName(QString const& _value) +{ + QString ret = _value; + if (_value.startsWith("<") && _value.endsWith(">")) + ret = ret.remove("<").remove(">").split(" - ").first(); + return ret; +} + void ClientModel::showDebugger() { ExecutionResult last = m_client->lastExecution(); @@ -446,7 +456,7 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t) //try to resolve contract for source level debugging auto nameIter = m_contractNames.find(code.address); CompiledContract const* compilerRes = nullptr; - if (nameIter != m_contractNames.end() && (compilerRes = m_codeModel->tryGetContract(nameIter->second))) //returned object is guaranteed to live till the end of event handler in main thread + if (nameIter != m_contractNames.end() && (compilerRes = m_codeModel->tryGetContract(resolveContractName(nameIter->second)))) //returned object is guaranteed to live till the end of event handler in main thread { eth::AssemblyItems assemblyItems = !_t.isConstructor() ? compilerRes->assemblyItems() : compilerRes->constructorAssemblyItems(); codes.back()->setDocument(compilerRes->documentId()); @@ -707,7 +717,7 @@ void ClientModel::onNewTransaction() auto contractAddressIter = m_contractNames.find(contractAddress); if (contractAddressIter != m_contractNames.end()) { - CompiledContract const& compilerRes = m_codeModel->contract(contractAddressIter->second); + CompiledContract const& compilerRes = m_codeModel->contract(resolveContractName(contractAddressIter->second)); const QContractDefinition* def = compilerRes.contract(); contract = def->name(); if (abi) diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 46cabe450..15cdc7086 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -53,10 +53,10 @@ struct SolidityType; struct TransactionSettings { TransactionSettings() {} - TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, bool _gasAuto, u256 _gasPrice, Secret _sender, int _isContractCall): - contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasAuto(_gasAuto), gasPrice(_gasPrice), sender(_sender), isContractCall(_isContractCall) {} + TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, bool _gasAuto, u256 _gasPrice, Secret _sender, int _isContractCreation): + contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasAuto(_gasAuto), gasPrice(_gasPrice), sender(_sender), isContractCreation(_isContractCreation) {} TransactionSettings(QString const& _stdContractName, QString const& _stdContractUrl): - contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl), isContractCall(true) {} + contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl), isContractCreation(true) {} /// Contract name QString contractId; @@ -76,8 +76,8 @@ struct TransactionSettings QString stdContractUrl; /// Sender Secret sender; - /// Is a call to a contract - bool isContractCall; + /// Tr deploys a contract + bool isContractCreation; }; @@ -231,6 +231,7 @@ private: QVariant formatValue(SolidityType const& _type, dev::u256 const& _value); QVariant formatStorageValue(SolidityType const& _type, std::map const& _storage, unsigned _offset, dev::u256 const& _slot); QString resolveToken(QString const& _value, std::vector
const& _contracts); + QString resolveContractName(QString const& _value); std::atomic m_running; std::atomic m_mining; diff --git a/mix/qml/QAddressView.qml b/mix/qml/QAddressView.qml index 19d98b166..c880f0904 100644 --- a/mix/qml/QAddressView.qml +++ b/mix/qml/QAddressView.qml @@ -30,6 +30,11 @@ Item return accountRef.get(trCombobox.currentIndex).type; } + function current() + { + return accountRef.get(trCombobox.currentIndex); + } + function load() { accountRef.clear(); diff --git a/mix/qml/StateDialog.qml b/mix/qml/StateDialog.qml index 13d01d474..f8da6dabd 100644 --- a/mix/qml/StateDialog.qml +++ b/mix/qml/StateDialog.qml @@ -436,7 +436,7 @@ Dialog { model: transactionsModel headerVisible: false TableViewColumn { - role: "name" + role: "label" title: qsTr("Name") width: 150 delegate: Item { @@ -476,7 +476,7 @@ Dialog { text: { if (styleData.row >= 0) return transactionsModel.get( - styleData.row).functionId + styleData.row).label else return "" } diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index 3eac14a11..a6069d620 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -57,10 +57,15 @@ Item { stdContract: t.stdContract ? true : false, parameters: {}, sender: t.sender, - isContractCall: t.isContractCall + isContractCreation: t.isContractCreation, + label: t.label }; - if (r.isContractCall === undefined) - r.isContractCall = true; //support for old project + + if (!r.label) + r.label = r.contractId + " " + r.functionId; + + if (r.isContractCreation === undefined) + r.isContractCreation = true; //support for old project for (var key in t.parameters) r.parameters[key] = t.parameters[key]; @@ -115,7 +120,8 @@ Item { stdContract: t.stdContract, sender: t.sender, parameters: {}, - isContractCall: t.isContractCall + isContractCreation: t.isContractCreation, + label: t.label }; for (var key in t.parameters) r.parameters[key] = t.parameters[key]; diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 84abb854b..d26fbaf5a 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -66,34 +66,46 @@ Dialog { contractIndex = 0; //@todo suggest unused contract contractComboBox.currentIndex = contractIndex; - loadFunctions(contractComboBox.currentValue()); + recipients.accounts = senderComboBox.model; + recipients.subType = "address"; + recipients.load(); + recipients.init(); + recipients.select(contractId); + + if (item.isContractCreation) + loadFunctions(contractComboBox.currentValue()); + else + loadFunctions(contractFromToken(recipients.currentValue())) selectFunction(functionId); + trType.checked = item.isContractCreation + trType.init(); + paramsModel = []; - if (functionId !== contractComboBox.currentValue()) + if (item.isContractCreation) + loadCtorParameters(); + else loadParameters(); - else { - var contract = codeModel.contracts[contractId]; - if (contract) { - var params = contract.contract.constructor.parameters; - for (var p = 0; p < params.length; p++) - loadParameter(params[p]); - } - } - initTypeLoader(); - trType.checked = item.isContractCall - trType.init(); - recipients.accounts = senderComboBox.model; - recipients.subType = "address"; - recipients.load(); - recipients.init(); - recipients.select(contractId); + visible = true; valueField.focus = true; } + function loadCtorParameters(contractId) + { + paramsModel = []; + console.log(contractId); + var contract = codeModel.contracts[contractId]; + if (contract) { + var params = contract.contract.constructor.parameters; + for (var p = 0; p < params.length; p++) + loadParameter(params[p]); + } + initTypeLoader(); + } + function loadFunctions(contractId) { functionsModel.clear(); @@ -104,9 +116,7 @@ Dialog { functionsModel.append({ text: functions[f].name }); } } - //append constructor - functionsModel.append({ text: contractId }); - + functionsModel.append({ text: "(transfert)" }); } function selectContract(contractName) @@ -144,7 +154,7 @@ Dialog { function loadParameters() { paramsModel = [] if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) { - var contract = codeModel.contracts[contractComboBox.currentValue()]; + var contract = codeModel.contracts[contractFromToken(recipients.currentValue())]; if (contract) { var func = contract.contract.functions[functionComboBox.currentIndex]; if (func) { @@ -201,17 +211,32 @@ Dialog { item.functionId = transactionDialog.functionId; } - item.isContractCall = trType.checked; - if (!item.isContractCall) + item.isContractCreation = trType.checked; + if (!item.isContractCreation) { - item.functionId = recipients.currentText; item.contractId = recipients.currentText; + item.label = item.contractId + " " + item.functionId; + if (recipients.current().type === "address") + item.functionId = "(transfert)"; + } + else + { + item.functionId = item.contractId; + item.label = qsTr("Deploy") + " " + item.contractId; } item.sender = senderComboBox.model[senderComboBox.currentIndex].secret; item.parameters = paramValues; return item; } + + function contractFromToken(token) + { + if (token.indexOf('<') === 0) + return token.replace("<", "").replace(">", "").split(" - ")[0]; + return token; + } + contentItem: Rectangle { color: transactionDialogStyle.generic.backgroundColor ColumnLayout { @@ -267,14 +292,17 @@ Dialog { function init() { - rowFunction.visible = checked; + rowFunction.visible = !checked; rowContract.visible = checked; rowRecipient.visible = !checked; paramLabel.visible = checked; paramScroll.visible = checked; + functionComboBox.enabled = !checked; + if (checked) + loadCtorParameters(contractComboBox.currentValue()); } - text: qsTr("is contract call") + text: qsTr("is contract creation") checked: true } } @@ -292,6 +320,14 @@ Dialog { QAddressView { id: recipients + onIndexChanged: + { + rowFunction.visible = current().type === "contract"; + paramLabel.visible = current().type === "contract"; + paramScroll.visible = current().type === "contract"; + if (!rowIsContract.checked) + loadFunctions(contractFromToken(recipients.currentValue())) + } } } @@ -317,7 +353,7 @@ Dialog { id: contractsModel } onCurrentIndexChanged: { - loadFunctions(currentValue()); + loadCtorParameters(currentValue()); } } } diff --git a/mix/qml/js/TransactionHelper.js b/mix/qml/js/TransactionHelper.js index 01fe65b5d..33072fdba 100644 --- a/mix/qml/js/TransactionHelper.js +++ b/mix/qml/js/TransactionHelper.js @@ -10,7 +10,8 @@ function defaultTransaction() gasPrice: createEther("100000", QEther.Wei), parameters: {}, stdContract: false, - isContractCall: true + isContractCreation: true, + label: "" }; } From 0e7d6d77e5be791b2479440b9b6b427a6d978f28 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 8 May 2015 17:36:29 +0200 Subject: [PATCH 005/157] small changes --- mix/qml/StateListModel.qml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index a6069d620..a7b83aec9 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -62,10 +62,8 @@ Item { }; if (!r.label) - r.label = r.contractId + " " + r.functionId; + r.label = r.contractId + " - " + r.functionId; - if (r.isContractCreation === undefined) - r.isContractCreation = true; //support for old project for (var key in t.parameters) r.parameters[key] = t.parameters[key]; From 3fc50e3615348b86e97725afe63a61ebb712da41 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 8 May 2015 18:12:49 +0200 Subject: [PATCH 006/157] bux fix --- mix/ClientModel.cpp | 12 ++++++++++-- mix/ClientModel.h | 1 + mix/qml/StateListModel.qml | 3 +++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index a58366046..8067f62c4 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -373,7 +373,7 @@ void ClientModel::executeSequence(vector const& _sequence, auto contractAddressIter = m_contractAddresses.find(transaction.contractId); if (contractAddressIter == m_contractAddresses.end() || newAddress != contractAddressIter->second) { - QString contractToken = "<" + transaction.contractId + " - " + QString::number(deployedContracts.size() - 1) + ">"; + QString contractToken = retrieveToken(transaction.contractId, deployedContracts); m_contractAddresses[contractToken] = newAddress; m_contractNames[newAddress] = contractToken; contractAddressesChanged(); @@ -382,7 +382,7 @@ void ClientModel::executeSequence(vector const& _sequence, } else { - auto contractAddressIter = m_contractAddresses.find(transaction.contractId); + auto contractAddressIter = m_contractAddresses.find(retrieveToken(transaction.contractId, deployedContracts)); if (contractAddressIter == m_contractAddresses.end()) { emit runFailed("Contract '" + transaction.contractId + tr(" not deployed.") + "' " + tr(" Cannot call ") + transaction.functionId); @@ -425,6 +425,14 @@ QString ClientModel::resolveToken(QString const& _value, vector
const& return ret; } +QString ClientModel::retrieveToken(QString const& _value, vector
const& _contracts) +{ + QString ret = _value; + if (!_value.startsWith("<") && !_value.endsWith(">")) + return "<" + _value + " - " + QString::number(_contracts.size() - 1) + ">"; + return ret; +} + QString ClientModel::resolveContractName(QString const& _value) { QString ret = _value; diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 15cdc7086..2ba37f593 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -232,6 +232,7 @@ private: QVariant formatStorageValue(SolidityType const& _type, std::map const& _storage, unsigned _offset, dev::u256 const& _slot); QString resolveToken(QString const& _value, std::vector
const& _contracts); QString resolveContractName(QString const& _value); + QString retrieveToken(QString const& _value, std::vector
const& _contracts); std::atomic m_running; std::atomic m_mining; diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index a7b83aec9..b4eed525d 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -64,6 +64,9 @@ Item { if (!r.label) r.label = r.contractId + " - " + r.functionId; + if (r.isContractCreation === undefined) + r.isContractCreation = r.functionId === r.contractId; + for (var key in t.parameters) r.parameters[key] = t.parameters[key]; From dc7df3cc0713561526bf547eb8dfaa8dda42d0da Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Sun, 10 May 2015 15:18:13 +0200 Subject: [PATCH 007/157] Test for Capability class Basic configuration for sending and receiving messgaes. --- test/libp2p/capability.cpp | 157 +++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 test/libp2p/capability.cpp diff --git a/test/libp2p/capability.cpp b/test/libp2p/capability.cpp new file mode 100644 index 000000000..2dcf9b4ba --- /dev/null +++ b/test/libp2p/capability.cpp @@ -0,0 +1,157 @@ +/* +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 capability.cpp +* @author Vladislav Gluhovsky +* @date May 2015 +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace dev; +using namespace dev::p2p; + +struct P2PFixture +{ + P2PFixture() { dev::p2p::NodeIPEndpoint::test_allowLocal = true; } + ~P2PFixture() { dev::p2p::NodeIPEndpoint::test_allowLocal = false; } +}; + +struct VerbosityHolder +{ + int m_oldLogVerbosity; + VerbosityHolder() : m_oldLogVerbosity(g_logVerbosity) { g_logVerbosity = 10; } + ~VerbosityHolder() { g_logVerbosity = m_oldLogVerbosity; } +}; + +class TestCapability : public Capability +{ + int m_cntReceivedMessages; + int m_testSum; + +public: + TestCapability(Session* _s, HostCapabilityFace* _h, unsigned _idOffset) : Capability(_s, _h, _idOffset), m_cntReceivedMessages(0), m_testSum(0) {} + virtual ~TestCapability() {} + int countReceivedMessages() { return m_cntReceivedMessages; } + int testSum() { return m_testSum; } + static std::string name() { return "test"; } + static u256 version() { return 2; } + static unsigned messageCount() { return UserPacket + 1; } + + void sendTestMessage(int _i) + { + RLPStream s; + prep(s, UserPacket, 1); + s << _i; + sealAndSend(s); + } + +protected: + virtual bool interpret(unsigned _id, RLP const& _r) override + { + cnote << "Capability::interpret(): custom message received"; + BOOST_REQUIRE_EQUAL(_id, UserPacket); + ++m_cntReceivedMessages; + int i = _r[0].toInt(); + m_testSum += i; + return true; + } +}; + +class TestHostCapability : public HostCapability, public Worker +{ +public: + TestHostCapability() : Worker("test") {} + virtual ~TestHostCapability() {} + + void sendTestMessage(NodeId const& _id, int _x) + { + for (auto i: peerSessions()) + if (_id == i.second->id) + i.first->cap().get()->sendTestMessage(_x); + } + + std::pair retrieveTestData(NodeId const& _id) + { + int cnt = 0; + int checksum = 0; + for (auto i : peerSessions()) + if (_id == i.second->id) + { + cnt += i.first->cap().get()->countReceivedMessages(); + checksum += i.first->cap().get()->testSum(); + } + + return std::pair(cnt, checksum); + } +}; + +BOOST_FIXTURE_TEST_SUITE(p2pCapability, P2PFixture) + +BOOST_AUTO_TEST_CASE(capability) +{ + VerbosityHolder verbosityHolder; + cnote << "Testing Capability..."; + + const char* const localhost = "127.0.0.1"; + NetworkPreferences prefs1(localhost, 30301, false); + NetworkPreferences prefs2(localhost, 30302, false); + + Host host1("Test", prefs1); + auto thc1 = host1.registerCapability(new TestHostCapability()); + host1.start(); + + Host host2("Test", prefs2); + auto thc2 = host2.registerCapability(new TestHostCapability()); + host2.start(); + + int const step = 10; + + for (int i = 0; i < 3000; i += step) + if (!host1.isStarted() || !host2.isStarted()) + this_thread::sleep_for(chrono::milliseconds(step)); + + BOOST_REQUIRE(host1.isStarted() && host2.isStarted()); + host1.requirePeer(host2.id(), NodeIPEndpoint(bi::address::from_string(localhost), prefs2.listenPort, prefs2.listenPort)); + + for (int i = 0; i < 3000; i += step) + if (!host1.peerCount() || !host2.peerCount()) + this_thread::sleep_for(chrono::milliseconds(step)); + + BOOST_REQUIRE(host1.peerCount() > 0 && host2.peerCount() > 0); + + int const target = 7; + int checksum = 0; + for (int i = 0; i < target; checksum += i++) + thc2->sendTestMessage(host1.id(), i); + + this_thread::sleep_for(chrono::seconds(1)); + std::pair testData = thc1->retrieveTestData(host2.id()); + BOOST_REQUIRE_EQUAL(target, testData.first); + BOOST_REQUIRE_EQUAL(checksum, testData.second); +} + +BOOST_AUTO_TEST_SUITE_END() + + From 438d2b44edd22348a0233c49884a45239454f4bd Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 11 May 2015 09:56:17 +0200 Subject: [PATCH 008/157] small changes --- mix/ClientModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 8067f62c4..519b7ddf3 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -390,7 +390,7 @@ void ClientModel::executeSequence(vector const& _sequence, emit runStateChanged(); return; } - callAddress(Address(address.toStdString()), encoder.encodedData(), transaction); + callAddress(contractAddressIter->second, encoder.encodedData(), transaction); } m_gasCosts.append(m_client->lastExecution().gasUsed); } From fa69d6a5298fc1c53dc83c8036463c7e4d02d1b1 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Mon, 11 May 2015 10:11:36 +0200 Subject: [PATCH 009/157] optional wallet blockChain tests, beacuse it takes a while --- test/TestHelper.cpp | 3 +++ test/TestHelper.h | 1 + test/libethereum/blockchain.cpp | 3 ++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 96e11e02c..79fdaa158 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -732,6 +732,8 @@ Options::Options() bigData = true; else if (arg == "--checkstate") checkState = true; + else if (arg == "--wallet") + wallet = true; else if (arg == "--all") { performance = true; @@ -739,6 +741,7 @@ Options::Options() memory = true; inputLimits = true; bigData = true; + wallet= true; } else if (arg == "--singletest" && i + 1 < argc) { diff --git a/test/TestHelper.h b/test/TestHelper.h index 02f509e4c..e63634053 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -195,6 +195,7 @@ public: bool memory = false; bool inputLimits = false; bool bigData = false; + bool wallet = false; /// @} /// Get reference to options diff --git a/test/libethereum/blockchain.cpp b/test/libethereum/blockchain.cpp index c5ac936fe..585a741b9 100644 --- a/test/libethereum/blockchain.cpp +++ b/test/libethereum/blockchain.cpp @@ -787,7 +787,8 @@ BOOST_AUTO_TEST_CASE(bcGasPricerTest) BOOST_AUTO_TEST_CASE(bcWalletTest) { - dev::test::executeTests("bcWalletTest", "/BlockTests",dev::test::getFolder(__FILE__) + "/BlockTestsFiller", dev::test::doBlockchainTests); + if (test::Options::get().wallet) + dev::test::executeTests("bcWalletTest", "/BlockTests",dev::test::getFolder(__FILE__) + "/BlockTestsFiller", dev::test::doBlockchainTests); } BOOST_AUTO_TEST_CASE(userDefinedFile) From 33d7e42866566d9fe225a4ab67eae05f7f52df5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 11 May 2015 11:38:11 +0200 Subject: [PATCH 010/157] CMake: set default RUNTIME_OUTPUT_DIRECTORY property to "bin" This commit changes output directory for runtime components (executables and DLLs) to "bin" directory. That allows running executables on Windows without need of install step. Closes ethereum/cpp-ethereum#1821 --- CMakeLists.txt | 1 + cmake/EthExecutableHelper.cmake | 33 +++++++++++++++++---------------- cmake/scripts/copydlls.cmake | 3 +-- libevmasm/CMakeLists.txt | 7 +------ 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ba214cce..4e7003692 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -295,6 +295,7 @@ message("-- EVMJIT Build LLVM-based JIT EVM (experimental!) ${EVMJIT}" message("------------------------------------------------------------------------") message("") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") set(CMAKE_THREAD_LIBS_INIT pthread) include(EthCompilerSettings) diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake index 1d1cb887b..d971a5f92 100644 --- a/cmake/EthExecutableHelper.cmake +++ b/cmake/EthExecutableHelper.cmake @@ -45,25 +45,26 @@ endmacro() macro(eth_copy_dlls EXECUTABLE DLLS) # dlls must be unsubstitud list variable (without ${}) in format - # optimized;path_to_dll.dll;debug;path_to_dlld.dll + # optimized;path_to_dll.dll;debug;path_to_dlld.dll list(GET ${DLLS} 1 DLL_RELEASE) list(GET ${DLLS} 3 DLL_DEBUG) + get_target_property(TARGET_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE} RUNTIME_OUTPUT_DIRECTORY) add_custom_command(TARGET ${EXECUTABLE} - POST_BUILD - COMMAND ${CMAKE_COMMAND} ARGS - -DDLL_RELEASE="${DLL_RELEASE}" - -DDLL_DEBUG="${DLL_DEBUG}" + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS + -DDLL_RELEASE="${DLL_RELEASE}" + -DDLL_DEBUG="${DLL_DEBUG}" -DCONF="$" - -DDESTINATION="${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" + -DDESTINATION="${TARGET_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}" -P "${ETH_SCRIPTS_DIR}/copydlls.cmake" ) endmacro() -# +# # this function requires the following variables to be specified: # ETH_DEPENDENCY_INSTALL_DIR # -# params: +# params: # QMLDIR # @@ -74,7 +75,7 @@ macro(eth_install_executable EXECUTABLE) set (one_value_args QMLDIR) set (multi_value_args DLLS) cmake_parse_arguments (ETH_INSTALL_EXECUTABLE "${options}" "${one_value_args}" "${multi_value_args}" "${extra_macro_args}") - + if (ETH_INSTALL_EXECUTABLE_QMLDIR) if (APPLE) set(eth_qml_dir "-qmldir=${ETH_INSTALL_EXECUTABLE_QMLDIR}") @@ -91,13 +92,14 @@ macro(eth_install_executable EXECUTABLE) WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} COMMAND sh ${CMAKE_SOURCE_DIR}/macdeployfix.sh ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app/Contents ) - + + get_target_property(TARGET_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE} RUNTIME_OUTPUT_DIRECTORY) # This tool and next will inspect linked libraries in order to determine which dependencies are required if (${CMAKE_CFG_INTDIR} STREQUAL ".") # TODO: This should only happen for GUI application - set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}.app") + set(APP_BUNDLE_PATH "${TARGET_RUNTIME_OUTPUT_DIRECTORY}/${EXECUTABLE}.app") else () - set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app") + set(APP_BUNDLE_PATH "${TARGET_RUNTIME_OUTPUT_DIRECTORY}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app") endif () install(CODE " @@ -111,14 +113,15 @@ macro(eth_install_executable EXECUTABLE) get_target_property(TARGET_LIBS ${EXECUTABLE} INTERFACE_LINK_LIBRARIES) string(REGEX MATCH "Qt5::Core" HAVE_QT ${TARGET_LIBS}) if ("${HAVE_QT}" STREQUAL "Qt5::Core") + get_target_property(TARGET_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE} RUNTIME_OUTPUT_DIRECTORY) add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND cmd /C "set PATH=${Qt5Core_DIR}/../../../bin;%PATH% && ${WINDEPLOYQT_APP} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.exe ${eth_qml_dir}" + COMMAND cmd /C "set PATH=${Qt5Core_DIR}/../../../bin;%PATH% && ${WINDEPLOYQT_APP} ${TARGET_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.exe ${eth_qml_dir}" WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ) #workaround for https://bugreports.qt.io/browse/QTBUG-42083 add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND cmd /C "(echo [Paths] & echo.Prefix=.)" > "qt.conf" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} VERBATIM + WORKING_DIRECTORY ${TARGET_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR} VERBATIM ) endif() @@ -144,5 +147,3 @@ macro(eth_install_executable EXECUTABLE) endif () endmacro() - - diff --git a/cmake/scripts/copydlls.cmake b/cmake/scripts/copydlls.cmake index 6d86b8e4e..57eb0ffd4 100644 --- a/cmake/scripts/copydlls.cmake +++ b/cmake/scripts/copydlls.cmake @@ -14,5 +14,4 @@ else () # Debug set(DLL ${DLL_DEBUG}) endif() -execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${DLL}" "${DESTINATION}") - +execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${DLL}" "${DESTINATION}") diff --git a/libevmasm/CMakeLists.txt b/libevmasm/CMakeLists.txt index f8150806f..eb8fea95c 100644 --- a/libevmasm/CMakeLists.txt +++ b/libevmasm/CMakeLists.txt @@ -19,15 +19,10 @@ set(EXECUTABLE evmasm) file(GLOB HEADERS "*.h") -if (ETH_STATIC) - add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) -else() - add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) -endif() +add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcrypto) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) - From faee123b4a0e337fc275b828637f51c02e63e0b9 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Mon, 11 May 2015 12:39:37 +0200 Subject: [PATCH 011/157] Coding Standards fix --- test/libp2p/capability.cpp | 50 +++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/test/libp2p/capability.cpp b/test/libp2p/capability.cpp index 2dcf9b4ba..2f1509e80 100644 --- a/test/libp2p/capability.cpp +++ b/test/libp2p/capability.cpp @@ -40,49 +40,43 @@ struct P2PFixture struct VerbosityHolder { - int m_oldLogVerbosity; - VerbosityHolder() : m_oldLogVerbosity(g_logVerbosity) { g_logVerbosity = 10; } - ~VerbosityHolder() { g_logVerbosity = m_oldLogVerbosity; } + int oldLogVerbosity; + VerbosityHolder(): oldLogVerbosity(g_logVerbosity) { g_logVerbosity = 10; } + ~VerbosityHolder() { g_logVerbosity = oldLogVerbosity; } }; -class TestCapability : public Capability +class TestCapability: public Capability { - int m_cntReceivedMessages; - int m_testSum; - public: - TestCapability(Session* _s, HostCapabilityFace* _h, unsigned _idOffset) : Capability(_s, _h, _idOffset), m_cntReceivedMessages(0), m_testSum(0) {} + TestCapability(Session* _s, HostCapabilityFace* _h, unsigned _idOffset): Capability(_s, _h, _idOffset), m_cntReceivedMessages(0), m_testSum(0) {} virtual ~TestCapability() {} int countReceivedMessages() { return m_cntReceivedMessages; } int testSum() { return m_testSum; } static std::string name() { return "test"; } static u256 version() { return 2; } static unsigned messageCount() { return UserPacket + 1; } - - void sendTestMessage(int _i) - { - RLPStream s; - prep(s, UserPacket, 1); - s << _i; - sealAndSend(s); - } + void sendTestMessage(int _i) { RLPStream s; sealAndSend(prep(s, UserPacket, 1) << _i); } protected: - virtual bool interpret(unsigned _id, RLP const& _r) override - { - cnote << "Capability::interpret(): custom message received"; - BOOST_REQUIRE_EQUAL(_id, UserPacket); - ++m_cntReceivedMessages; - int i = _r[0].toInt(); - m_testSum += i; - return true; - } + virtual bool interpret(unsigned _id, RLP const& _r) override; + + int m_cntReceivedMessages; + int m_testSum; }; -class TestHostCapability : public HostCapability, public Worker +bool TestCapability::interpret(unsigned _id, RLP const& _r) +{ + cnote << "Capability::interpret(): custom message received"; + BOOST_ASSERT(_id == UserPacket); + ++m_cntReceivedMessages; + m_testSum += _r[0].toInt(); + return true; +} + +class TestHostCapability: public HostCapability, public Worker { public: - TestHostCapability() : Worker("test") {} + TestHostCapability(): Worker("test") {} virtual ~TestHostCapability() {} void sendTestMessage(NodeId const& _id, int _x) @@ -96,7 +90,7 @@ public: { int cnt = 0; int checksum = 0; - for (auto i : peerSessions()) + for (auto i: peerSessions()) if (_id == i.second->id) { cnt += i.first->cap().get()->countReceivedMessages(); From 979c5851f9f846b7dfbde0be8e9c8a92b873083f Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 6 May 2015 19:15:14 +0200 Subject: [PATCH 012/157] Reuse state during common subexpression elimination. --- libevmasm/Assembly.cpp | 80 ++++++++++----------- libevmasm/CommonSubexpressionEliminator.cpp | 51 +++++++++---- libevmasm/CommonSubexpressionEliminator.h | 14 ++-- libevmasm/ControlFlowGraph.cpp | 22 ++++-- 4 files changed, 94 insertions(+), 73 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 9530ded49..abcd44516 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -311,54 +311,45 @@ 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..."; + copt << "Performing optimisation..."; { ControlFlowGraph cfg(m_items); - AssemblyItems optItems; + AssemblyItems optimisedItems; 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(); - m_items = move(optItems); - count++; - } - } - - copt << "Performing common subexpression elimination..."; - for (auto iter = m_items.begin(); iter != m_items.end();) - { - //@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; - bool shouldReplace = false; - try - { - optItems = eliminator.getOptimizedItems(); - shouldReplace = (optItems.size() < size_t(iter - orig)); - } - catch (StackTooDeepException const&) - { - // This might happen if the opcode reconstruction is not as efficient - // as the hand-crafted code. - } - - if (shouldReplace) - { - copt << "Old size: " << (iter - orig) << ", new size: " << optItems.size(); - count++; - for (auto moveIter = optItems.begin(); moveIter != optItems.end(); ++orig, ++moveIter) - *orig = move(*moveIter); - iter = m_items.erase(orig, iter); + assertThrow(!!block.startState, OptimizerException, ""); + CommonSubexpressionEliminator eliminator(*block.startState); + auto iter = m_items.begin() + block.begin; + auto const end = m_items.begin() + block.end; + while (iter < end) + { + auto orig = iter; + iter = eliminator.feedItems(iter, end); + bool shouldReplace = false; + AssemblyItems optimisedChunk; + try + { + optimisedChunk = eliminator.getOptimizedItems(); + shouldReplace = (optimisedChunk.size() < size_t(iter - orig)); + } + catch (StackTooDeepException const&) + { + // This might happen if the opcode reconstruction is not as efficient + // as the hand-crafted code. + } + + if (shouldReplace) + { + copt << "Old size: " << (iter - orig) << ", new size: " << optimisedChunk.size(); + count++; + optimisedItems += optimisedChunk; + } + else + copy(orig, iter, back_inserter(optimisedItems)); + } } + if (optimisedItems.size() < m_items.size()) + m_items = move(optimisedItems); } } @@ -461,7 +452,8 @@ bytes Assembly::assemble() const for (auto const& i: tagRef) { bytesRef r(ret.data() + i.first, bytesPerTag); - toBigEndian(tagPos[i.second], r); + //@todo in the failure case, we could use the position of the invalid jumpdest + toBigEndian(i.second < tagPos.size() ? tagPos[i.second] : (1 << (8 * bytesPerTag)) - 1, r); } if (!m_data.empty()) diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index 4b85eba40..5beb7966f 100644 --- a/libevmasm/CommonSubexpressionEliminator.cpp +++ b/libevmasm/CommonSubexpressionEliminator.cpp @@ -45,16 +45,22 @@ vector CommonSubexpressionEliminator::getOptimizedItems() 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_state.expressionClasses(), m_storeOperations).generateCode( m_initialState.stackHeight(), initialStackContents, targetStackContents ); if (m_breakingItem) + { items.push_back(*m_breakingItem); + m_state.feedItem(*m_breakingItem); + } + + // cleanup + m_initialState = m_state; + m_breakingItem = nullptr; + m_storeOperations.clear(); + return items; } @@ -113,6 +119,7 @@ AssemblyItems CSECodeGenerator::generateCode( { m_stackHeight = _initialStackHeight; m_stack = _initialStack; + m_targetStack = _targetStackContents; for (auto const& item: m_stack) if (!m_classPositions.count(item.second)) m_classPositions[item.second] = item.first; @@ -122,7 +129,7 @@ AssemblyItems CSECodeGenerator::generateCode( // generate the dependency graph starting from final storage and memory writes and target stack contents for (auto const& p: m_storeOperations) addDependencies(p.second.back().expression); - for (auto const& targetItem: _targetStackContents) + for (auto const& targetItem: m_targetStack) { m_finalClasses.insert(targetItem.second); addDependencies(targetItem.second); @@ -141,8 +148,10 @@ AssemblyItems CSECodeGenerator::generateCode( generateClassElement(seqAndId.second, true); // generate the target stack elements - for (auto const& targetItem: _targetStackContents) + for (auto const& targetItem: m_targetStack) { + if (m_stack.count(targetItem.first) && m_stack.at(targetItem.first) == targetItem.second) + continue; // already there int position = generateClassElement(targetItem.second); assertThrow(position != c_invalidPosition, OptimizerException, ""); if (position == targetItem.first) @@ -164,21 +173,24 @@ AssemblyItems CSECodeGenerator::generateCode( // check validity int finalHeight = 0; - if (!_targetStackContents.empty()) + if (!m_targetStack.empty()) // have target stack, so its height should be the final height - finalHeight = (--_targetStackContents.end())->first; + finalHeight = (--m_targetStack.end())->first; else if (!_initialStack.empty()) // no target stack, only erase the initial stack finalHeight = _initialStack.begin()->first - 1; else // neither initial no target stack, no change in height - finalHeight = 0; + finalHeight = _initialStackHeight; assertThrow(finalHeight == m_stackHeight, OptimizerException, "Incorrect final stack height."); + return m_generatedItems; } void CSECodeGenerator::addDependencies(Id _c) { + if (m_classPositions.count(_c)) + return; // it is already on the stack if (m_neededBy.count(_c)) return; // we already computed the dependencies for _c ExpressionClasses::Expression expr = m_expressionClasses.representative(_c); @@ -340,7 +352,7 @@ int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) // this will not append a swap but remove the one that is already there appendOrRemoveSwap(m_stackHeight - 1, location); for (auto arg: arguments) - if (canBeRemoved(arg, _c)) + if (m_classPositions[arg] != c_invalidPosition && canBeRemoved(arg, _c)) m_classPositions[arg] = c_invalidPosition; for (size_t i = 0; i < arguments.size(); ++i) m_stack.erase(m_stackHeight - i); @@ -371,13 +383,22 @@ int CSECodeGenerator::classElementPosition(Id _id) const return m_classPositions.at(_id); } -bool CSECodeGenerator::canBeRemoved(Id _element, Id _result) +bool CSECodeGenerator::canBeRemoved(Id _element, Id _result, int _fromPosition) { - // Returns false if _element is finally needed or is needed by a class that has not been - // computed yet. Note that m_classPositions also includes classes that were deleted in the meantime. - if (m_finalClasses.count(_element)) - return false; + // Default for _fromPosition is the canonical position of the element. + if (_fromPosition == c_invalidPosition) + _fromPosition = classElementPosition(_element); + bool isCopy = _fromPosition != classElementPosition(_element); + if (m_finalClasses.count(_element)) + // It is part of the target stack. It can be removed if it is a copy that is not in the target position. + return isCopy && (!m_targetStack.count(_fromPosition) || m_targetStack[_fromPosition] != _element); + else if (isCopy) + // It is only a copy, can be removed. + return true; + + // Can be removed unless it is needed by a class that has not been computed yet. + // Note that m_classPositions also includes classes that were deleted in the meantime. auto range = m_neededBy.equal_range(_element); for (auto it = range.first; it != range.second; ++it) if (it->second != _result && !m_classPositions.count(it->second)) @@ -391,7 +412,7 @@ bool CSECodeGenerator::removeStackTopIfPossible() return false; assertThrow(m_stack.count(m_stackHeight) > 0, OptimizerException, ""); Id top = m_stack[m_stackHeight]; - if (!canBeRemoved(top)) + if (!canBeRemoved(top, Id(-1), m_stackHeight)) return false; m_generatedItems.push_back(AssemblyItem(Instruction::POP)); m_stack.erase(m_stackHeight); diff --git a/libevmasm/CommonSubexpressionEliminator.h b/libevmasm/CommonSubexpressionEliminator.h index 6e1ba40b3..2a9a31255 100644 --- a/libevmasm/CommonSubexpressionEliminator.h +++ b/libevmasm/CommonSubexpressionEliminator.h @@ -71,13 +71,6 @@ public: /// @returns the resulting items after optimization. AssemblyItems getOptimizedItems(); - /// Streams debugging information to @a _out. - std::ostream& stream( - std::ostream& _out, - std::map _initialStack = std::map(), - std::map _targetStack = std::map() - ) const; - private: /// Feeds the item into the system for analysis. void feedItem(AssemblyItem const& _item, bool _copyItem = false); @@ -134,8 +127,9 @@ private: /// @note throws an exception if it is not on the stack. int classElementPosition(Id _id) const; - /// @returns true if @a _element can be removed - in general or, if given, while computing @a _result. - bool canBeRemoved(Id _element, Id _result = Id(-1)); + /// @returns true if the copy of @a _element can be removed from stack position _fromPosition + /// - in general or, if given, while computing @a _result. + bool canBeRemoved(Id _element, Id _result = Id(-1), int _fromPosition = c_invalidPosition); /// Appends code to remove the topmost stack element if it can be removed. bool removeStackTopIfPossible(); @@ -167,6 +161,7 @@ private: std::map, StoreOperations> m_storeOperations; /// The set of equivalence classes that should be present on the stack at the end. std::set m_finalClasses; + std::map m_targetStack; }; template @@ -175,6 +170,7 @@ _AssemblyItemIterator CommonSubexpressionEliminator::feedItems( _AssemblyItemIterator _end ) { + assertThrow(!m_breakingItem, OptimizerException, "Invalid use of CommonSubexpressionEliminator."); for (; _iterator != _end && !SemanticInformation::breaksCSEAnalysisBlock(*_iterator); ++_iterator) feedItem(*_iterator); if (_iterator != _end) diff --git a/libevmasm/ControlFlowGraph.cpp b/libevmasm/ControlFlowGraph.cpp index 2e28317a3..7ed56ff1a 100644 --- a/libevmasm/ControlFlowGraph.cpp +++ b/libevmasm/ControlFlowGraph.cpp @@ -142,7 +142,7 @@ void ControlFlowGraph::removeUnusedBlocks() BasicBlock const& block = m_blocks.at(blocksToProcess.back()); blocksToProcess.pop_back(); for (BlockId tag: block.pushedTags) - if (!neededBlocks.count(tag)) + if (!neededBlocks.count(tag) && m_blocks.count(tag)) { neededBlocks.insert(tag); blocksToProcess.push_back(tag); @@ -191,12 +191,12 @@ void ControlFlowGraph::setPrevLinks() if (push.type() != PushTag) continue; BlockId nextId(push.data()); - if (m_blocks.at(nextId).prev) + if (m_blocks.count(nextId) && m_blocks.at(nextId).prev) continue; bool hasLoop = false; - for (BlockId id = nextId; id && !hasLoop; id = m_blocks.at(id).next) + for (BlockId id = nextId; id && m_blocks.count(id) && !hasLoop; id = m_blocks.at(id).next) hasLoop = (id == blockId); - if (hasLoop) + if (hasLoop || !m_blocks.count(nextId)) continue; m_blocks[nextId].prev = blockId; @@ -225,6 +225,8 @@ void ControlFlowGraph::gatherKnowledge() { //@todo we might have to do something like incrementing the sequence number for each JUMPDEST assertThrow(!!workQueue.back().first, OptimizerException, ""); + if (!m_blocks.count(workQueue.back().first)) + continue; // too bad, we do not know the tag, probably an invalid jump BasicBlock& block = m_blocks.at(workQueue.back().first); KnownStatePointer state = workQueue.back().second; workQueue.pop_back(); @@ -281,6 +283,15 @@ void ControlFlowGraph::gatherKnowledge() ) workQueue.push_back(make_pair(block.next, state->copy())); } + + // Remove all blocks we never visited here. This might happen because a tag is pushed but + // never used for a JUMP. + // Note that this invalidates some contents of pushedTags + for (auto it = m_blocks.begin(); it != m_blocks.end();) + if (!it->second.startState) + m_blocks.erase(it++); + else + it++; } BasicBlocks ControlFlowGraph::rebuildCode() @@ -288,7 +299,8 @@ BasicBlocks ControlFlowGraph::rebuildCode() map pushes; for (auto& idAndBlock: m_blocks) for (BlockId ref: idAndBlock.second.pushedTags) - pushes[ref]++; + if (m_blocks.count(ref)) + pushes[ref]++; set blocksToAdd; for (auto it: m_blocks) From 1492fe2a88a67c12a544ef48857e94c2f10e1892 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 7 May 2015 18:31:21 +0200 Subject: [PATCH 013/157] Store alternative stack locations during code generation. --- libevmasm/CommonSubexpressionEliminator.cpp | 80 +++++++++++---------- libevmasm/CommonSubexpressionEliminator.h | 8 +-- 2 files changed, 45 insertions(+), 43 deletions(-) diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index 5beb7966f..e369c9dbc 100644 --- a/libevmasm/CommonSubexpressionEliminator.cpp +++ b/libevmasm/CommonSubexpressionEliminator.cpp @@ -121,10 +121,7 @@ AssemblyItems CSECodeGenerator::generateCode( m_stack = _initialStack; m_targetStack = _targetStackContents; for (auto const& item: m_stack) - if (!m_classPositions.count(item.second)) - m_classPositions[item.second] = item.first; - - // @todo: provide information about the positions of copies of class elements + m_classPositions[item.second].insert(item.first); // generate the dependency graph starting from final storage and memory writes and target stack contents for (auto const& p: m_storeOperations) @@ -152,11 +149,12 @@ AssemblyItems CSECodeGenerator::generateCode( { if (m_stack.count(targetItem.first) && m_stack.at(targetItem.first) == targetItem.second) continue; // already there - int position = generateClassElement(targetItem.second); - assertThrow(position != c_invalidPosition, OptimizerException, ""); - if (position == targetItem.first) + generateClassElement(targetItem.second); + assertThrow(!m_classPositions[targetItem.second].empty(), OptimizerException, ""); + if (m_classPositions[targetItem.second].count(targetItem.first)) continue; SourceLocation const& location = m_expressionClasses.representative(targetItem.second).item->getLocation(); + int position = classElementPosition(targetItem.second); if (position < targetItem.first) // it is already at its target, we need another copy appendDup(position, location); @@ -266,19 +264,23 @@ void CSECodeGenerator::addDependencies(Id _c) } } -int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) +void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) { + for (auto it: m_classPositions) + for (auto p: it.second) + if (p > m_stackHeight) + assertThrow(false, OptimizerException, ""); // do some cleanup removeStackTopIfPossible(); if (m_classPositions.count(_c)) { assertThrow( - m_classPositions[_c] != c_invalidPosition, + !m_classPositions[_c].empty(), OptimizerException, "Element already removed but still needed." ); - return m_classPositions[_c]; + return; } ExpressionClasses::Expression const& expr = m_expressionClasses.representative(_c); assertThrow( @@ -351,16 +353,16 @@ int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) m_generatedItems.back() == AssemblyItem(Instruction::SWAP1)) // this will not append a swap but remove the one that is already there appendOrRemoveSwap(m_stackHeight - 1, location); - for (auto arg: arguments) - if (m_classPositions[arg] != c_invalidPosition && canBeRemoved(arg, _c)) - m_classPositions[arg] = c_invalidPosition; for (size_t i = 0; i < arguments.size(); ++i) + { + m_classPositions[m_stack[m_stackHeight - i]].erase(m_stackHeight - i); m_stack.erase(m_stackHeight - i); + } appendItem(*expr.item); if (expr.item->type() != Operation || instructionInfo(expr.item->instruction()).ret == 1) { m_stack[m_stackHeight] = _c; - return m_classPositions[_c] = m_stackHeight; + m_classPositions[_c].insert(m_stackHeight); } else { @@ -369,18 +371,18 @@ int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) OptimizerException, "Invalid number of return values." ); - return m_classPositions[_c] = c_invalidPosition; + m_classPositions[_c]; // ensure it is created to mark the expression as generated } } int CSECodeGenerator::classElementPosition(Id _id) const { assertThrow( - m_classPositions.count(_id) && m_classPositions.at(_id) != c_invalidPosition, + m_classPositions.count(_id) && !m_classPositions.at(_id).empty(), OptimizerException, "Element requested but is not present." ); - return m_classPositions.at(_id); + return *max_element(m_classPositions.at(_id).begin(), m_classPositions.at(_id).end()); } bool CSECodeGenerator::canBeRemoved(Id _element, Id _result, int _fromPosition) @@ -389,20 +391,19 @@ bool CSECodeGenerator::canBeRemoved(Id _element, Id _result, int _fromPosition) if (_fromPosition == c_invalidPosition) _fromPosition = classElementPosition(_element); - bool isCopy = _fromPosition != classElementPosition(_element); + bool haveCopy = m_classPositions.at(_element).size() > 1; if (m_finalClasses.count(_element)) // It is part of the target stack. It can be removed if it is a copy that is not in the target position. - return isCopy && (!m_targetStack.count(_fromPosition) || m_targetStack[_fromPosition] != _element); - else if (isCopy) - // It is only a copy, can be removed. - return true; - - // Can be removed unless it is needed by a class that has not been computed yet. - // Note that m_classPositions also includes classes that were deleted in the meantime. - auto range = m_neededBy.equal_range(_element); - for (auto it = range.first; it != range.second; ++it) - if (it->second != _result && !m_classPositions.count(it->second)) - return false; + return haveCopy && (!m_targetStack.count(_fromPosition) || m_targetStack[_fromPosition] != _element); + else if (!haveCopy) + { + // Can be removed unless it is needed by a class that has not been computed yet. + // Note that m_classPositions also includes classes that were deleted in the meantime. + auto range = m_neededBy.equal_range(_element); + for (auto it = range.first; it != range.second; ++it) + if (it->second != _result && !m_classPositions.count(it->second)) + return false; + } return true; } @@ -414,9 +415,9 @@ bool CSECodeGenerator::removeStackTopIfPossible() Id top = m_stack[m_stackHeight]; if (!canBeRemoved(top, Id(-1), m_stackHeight)) return false; - m_generatedItems.push_back(AssemblyItem(Instruction::POP)); + m_classPositions[m_stack[m_stackHeight]].erase(m_stackHeight); m_stack.erase(m_stackHeight); - m_stackHeight--; + appendItem(AssemblyItem(Instruction::POP)); return true; } @@ -428,6 +429,7 @@ void CSECodeGenerator::appendDup(int _fromPosition, SourceLocation const& _locat assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access."); appendItem(AssemblyItem(dupInstruction(instructionNum), _location)); m_stack[m_stackHeight] = m_stack[_fromPosition]; + m_classPositions[m_stack[m_stackHeight]].insert(m_stackHeight); } void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation const& _location) @@ -439,13 +441,15 @@ void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation cons assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep."); assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access."); appendItem(AssemblyItem(swapInstruction(instructionNum), _location)); - // The value of a class can be present in multiple locations on the stack. We only update the - // "canonical" one that is tracked by m_classPositions - if (m_classPositions[m_stack[m_stackHeight]] == m_stackHeight) - m_classPositions[m_stack[m_stackHeight]] = _fromPosition; - if (m_classPositions[m_stack[_fromPosition]] == _fromPosition) - m_classPositions[m_stack[_fromPosition]] = m_stackHeight; - swap(m_stack[m_stackHeight], m_stack[_fromPosition]); + + if (m_stack[m_stackHeight] != m_stack[_fromPosition]) + { + m_classPositions[m_stack[m_stackHeight]].erase(m_stackHeight); + m_classPositions[m_stack[m_stackHeight]].insert(_fromPosition); + m_classPositions[m_stack[_fromPosition]].erase(_fromPosition); + m_classPositions[m_stack[_fromPosition]].insert(m_stackHeight); + swap(m_stack[m_stackHeight], m_stack[_fromPosition]); + } if (m_generatedItems.size() >= 2 && SemanticInformation::isSwapInstruction(m_generatedItems.back()) && *(m_generatedItems.end() - 2) == m_generatedItems.back()) diff --git a/libevmasm/CommonSubexpressionEliminator.h b/libevmasm/CommonSubexpressionEliminator.h index 2a9a31255..a35e31d90 100644 --- a/libevmasm/CommonSubexpressionEliminator.h +++ b/libevmasm/CommonSubexpressionEliminator.h @@ -119,10 +119,8 @@ private: void addDependencies(Id _c); /// Produce code that generates the given element if it is not yet present. - /// @returns the stack position of the element or c_invalidPosition if it does not actually - /// generate a value on the stack. /// @param _allowSequenced indicates that sequence-constrained operations are allowed - int generateClassElement(Id _c, bool _allowSequenced = false); + void generateClassElement(Id _c, bool _allowSequenced = false); /// @returns the position of the representative of the given id on the stack. /// @note throws an exception if it is not on the stack. int classElementPosition(Id _id) const; @@ -151,8 +149,8 @@ private: std::multimap m_neededBy; /// Current content of the stack. std::map m_stack; - /// Current positions of equivalence classes, equal to c_invalidPosition if already deleted. - std::map m_classPositions; + /// Current positions of equivalence classes, equal to the empty set if already deleted. + std::map> m_classPositions; /// The actual eqivalence class items and how to compute them. ExpressionClasses& m_expressionClasses; From 12f3446bf9f87b1e3450dfb551b3039fe578e638 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 8 May 2015 12:40:11 +0200 Subject: [PATCH 014/157] Tests. --- test/libsolidity/SolidityOptimizer.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 3cb6a536a..4986b1469 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -251,6 +251,27 @@ BOOST_AUTO_TEST_CASE(function_calls) compareVersions("f(uint256)", 36); } +BOOST_AUTO_TEST_CASE(storage_write_in_loops) +{ + char const* sourceCode = R"( + contract test { + uint d; + function f(uint a) returns (uint r) { + var x = d; + for (uint i = 1; i < a * a; i++) { + r = d; + d = i; + } + + } + } + )"; + compileBothVersions(sourceCode); + compareVersions("f(uint256)", 0); + compareVersions("f(uint256)", 10); + compareVersions("f(uint256)", 36); +} + BOOST_AUTO_TEST_CASE(cse_intermediate_swap) { eth::KnownState state; From a62174b3ac4c9714f73b6860859e304b858f232b Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 11 May 2015 15:09:47 +0200 Subject: [PATCH 015/157] - Remove contract source. - Bug fix when when removing a project file. --- mix/ClientModel.cpp | 1 - mix/CodeModel.cpp | 13 +++++++++++++ mix/CodeModel.h | 2 ++ mix/FileIo.cpp | 6 ++++++ mix/FileIo.h | 2 ++ mix/qml/CodeEditorView.qml | 19 ++++++++++++++++--- mix/qml/FilesSection.qml | 20 ++++++++++++++++++-- mix/qml/js/ProjectModel.js | 16 +++++++++++----- mix/test/qml/TestMain.qml | 1 + mix/test/qml/js/TestProject.js | 14 ++++++++++++++ 10 files changed, 83 insertions(+), 11 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index c558c71f3..9da294458 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -315,7 +315,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; } 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/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/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..05ba5f897 100644 --- a/mix/qml/FilesSection.qml +++ b/mix/qml/FilesSection.qml @@ -241,8 +241,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; @@ -268,6 +273,17 @@ Rectangle } } } + + Menu { + id: contextMenuContract + MenuItem { + text: qsTr("Delete") + onTriggered: { + projectModel.removeDocument(documentId); + wrapperItem.removeDocument(documentId); + } + } + } } } } diff --git a/mix/qml/js/ProjectModel.js b/mix/qml/js/ProjectModel.js index 6ec906996..51036f9c2 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 null; + 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/TestProject.js b/mix/test/qml/js/TestProject.js index 49b5ea51f..7ff482c58 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, null)*/ +} From 8523e9cce5a74b6f16f35416c4d6f1b45c4e8e1a Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Mon, 11 May 2015 15:59:57 +0200 Subject: [PATCH 016/157] add identity contract tests --- .../stPreCompiledContractsFiller.json | 379 ++++++++++++++++++ 1 file changed, 379 insertions(+) diff --git a/test/libethereum/StateTestsFiller/stPreCompiledContractsFiller.json b/test/libethereum/StateTestsFiller/stPreCompiledContractsFiller.json index 69e2456fb..41f5bc345 100644 --- a/test/libethereum/StateTestsFiller/stPreCompiledContractsFiller.json +++ b/test/libethereum/StateTestsFiller/stPreCompiledContractsFiller.json @@ -1038,6 +1038,385 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } + }, + + "CallIdentitiy_0": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "storage" : { + "0x" : "0000000000000000000000000000000000000000000000000000000000000001" + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "0x600160005260206000602060006000600460fff1600051600055", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallIdentitiy_1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "storage" : { + "0x" : "0x00", + "0x02" : "0x01" + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ [[ 2 ]] (CALL 500 4 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallIdentity_1_nonzeroValue": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "100000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { + "0000000000000000000000000000000000000004" : { + "balance" : "19" + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "storage" : { + "0x" : "0x00", + "0x02" : "0x01" + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "200000000", + "nonce" : "0", + "code" : "{ [[ 2 ]] (CALL 200000 4 0x13 0 0 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallIdentity_2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "storage" : { + "0x" : "0x000000000000000000000000000000000000000000000000000000f34578907f", + "0x02" : "0x01" + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 4 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallIdentity_3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "storage" : { + "0x" : "0x000000000000000000000000000000000000000000000000000000f34578907f", + "0x02" : "0x01" + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 4 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallIdentity_4": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "storage" : { + "0x" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x02" : "0x01" + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 100 4 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallIdentity_4_gas18": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "storage" : { + "0x" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x02" : "0x01" + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 18 4 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallIdentity_4_gas17": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "storage" : { + "0x" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0x02" : "0x00" + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 17 4 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "365224", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "CallIdentity_5": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "storage" : { + "0x" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 600 4 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "10000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } } } From 579d6f4e32263c7da41931a4b2aec36aee21d683 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 11 May 2015 16:40:28 +0200 Subject: [PATCH 017/157] Compute state intersection. --- libevmasm/KnownState.cpp | 47 +++++++++++++++++++------- test/libsolidity/SolidityOptimizer.cpp | 36 ++++++++++++++++++++ 2 files changed, 71 insertions(+), 12 deletions(-) diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index 41ac4802b..d6fbde2d9 100644 --- a/libevmasm/KnownState.cpp +++ b/libevmasm/KnownState.cpp @@ -160,23 +160,46 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool return op; } -void KnownState::reduceToCommonKnowledge(KnownState const& /*_other*/) +/// Helper function for KnownState::reduceToCommonKnowledge, removes everything from +/// _this which is not in or not equal to the value in _other. +template void intersect( + _Mapping& _this, + _Mapping const& _other, + function<_KeyType(_KeyType)> const& _keyTrans = [](_KeyType _k) { return _k; } +) +{ + for (auto it = _this.begin(); it != _this.end();) + if (_other.count(_keyTrans(it->first)) && _other.at(_keyTrans(it->first)) == it->second) + ++it; + else + it = _this.erase(it); +} + +void KnownState::reduceToCommonKnowledge(KnownState const& _other) { - //@todo - *this = KnownState(m_expressionClasses); + int stackDiff = m_stackHeight - _other.m_stackHeight; + function stackKeyTransform = [=](int _key) -> int { return _key - stackDiff; }; + intersect(m_stackElements, _other.m_stackElements, stackKeyTransform); + // Use the smaller stack height. Essential to terminate in case of loops. + if (m_stackHeight > _other.m_stackHeight) + { + map shiftedStack; + for (auto const& stackElement: m_stackElements) + shiftedStack[stackElement.first - stackDiff] = stackElement.second; + m_stackElements = move(shiftedStack); + m_stackHeight = _other.m_stackHeight; + } + + intersect(m_storageContent, _other.m_storageContent); + intersect(m_memoryContent, _other.m_memoryContent); } 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() - ); + return m_storageContent == _other.m_storageContent && + m_memoryContent == _other.m_memoryContent && + m_stackHeight == _other.m_stackHeight && + m_stackElements == _other.m_stackElements; } ExpressionClasses::Id KnownState::stackElement(int _stackHeight, SourceLocation const& _location) diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 4986b1469..e50469dd6 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -272,6 +272,42 @@ BOOST_AUTO_TEST_CASE(storage_write_in_loops) compareVersions("f(uint256)", 36); } +BOOST_AUTO_TEST_CASE(retain_information_in_branches) +{ + // This tests that the optimizer knows that we already have "z == sha3(y)" inside both branches. + char const* sourceCode = R"( + contract c { + bytes32 d; + uint a; + function f(uint x, bytes32 y) returns (uint r_a, bytes32 r_d) { + bytes32 z = sha3(y); + if (x > 8) { + z = sha3(y); + a = x; + } else { + z = sha3(y); + a = x; + } + r_a = a; + r_d = d; + } + } + )"; + compileBothVersions(sourceCode); + compareVersions("f(uint256,bytes32)", 0, "abc"); + compareVersions("f(uint256,bytes32)", 8, "def"); + compareVersions("f(uint256,bytes32)", 10, "ghi"); + + m_optimize = true; + bytes optimizedBytecode = compileAndRun(sourceCode, 0, "c"); + size_t numSHA3s = 0; + eth::eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) { + if (_instr == eth::Instruction::SHA3) + numSHA3s++; + }); + BOOST_CHECK_EQUAL(1, numSHA3s); +} + BOOST_AUTO_TEST_CASE(cse_intermediate_swap) { eth::KnownState state; From dba2756da8a5e8cebd5ee5457d8046c252cf0f3c Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 11 May 2015 16:49:52 +0200 Subject: [PATCH 018/157] add test --- mix/qml/js/ProjectModel.js | 2 +- mix/test/qml/js/TestDebugger.js | 7 +++++-- mix/test/qml/js/TestProject.js | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/mix/qml/js/ProjectModel.js b/mix/qml/js/ProjectModel.js index 51036f9c2..6fce7686d 100644 --- a/mix/qml/js/ProjectModel.js +++ b/mix/qml/js/ProjectModel.js @@ -295,7 +295,7 @@ function renameDocument(documentId, newName) { function getDocument(documentId) { var i = getDocumentIndex(documentId); if (i === -1) - return null; + return undefined; else return projectListModel.get(i); } 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 7ff482c58..fe1023f05 100644 --- a/mix/test/qml/js/TestProject.js +++ b/mix/test/qml/js/TestProject.js @@ -47,7 +47,7 @@ function test_multipleContractsSameFile() function test_deleteFile() { - /*newProject(); + newProject(); var path = mainApplication.projectModel.projectPath; createHtml("page1.html", "
Fail
"); createHtml("page2.html", "
Fail
"); @@ -56,5 +56,5 @@ function test_deleteFile() mainApplication.projectModel.closeProject(function(){}); mainApplication.projectModel.loadProject(path); var doc = mainApplication.projectModel.getDocument("page2.html"); - verify(doc, null)*/ + verify(!doc, "page2.html has not been removed"); } From 30ca78aa0b2f73999731c15d153ec629e20eea7e Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 11 May 2015 17:16:07 +0200 Subject: [PATCH 019/157] small changes --- mix/ClientModel.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 87230664f..5f6a6c26c 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -256,9 +256,7 @@ void ClientModel::setupState(QVariantMap _state) u256 gasPrice = (qvariant_cast(transaction.value("gasPrice")))->toU256Wei(); QString sender = transaction.value("sender").toString(); bool isStdContract = transaction.value("stdContract").toBool(); - bool isContractCreation; - if (!transaction.value("isContractCreation").isNull()) - isContractCreation = transaction.value("isContractCreation").toBool(); + bool isContractCreation = transaction.value("isContractCreation").toBool(); if (isStdContract) { if (contractId.isEmpty()) //TODO: This is to support old project files, remove later From 23d4ac1adb11e6b1689117fe7ddf432d57b2f836 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Mon, 11 May 2015 17:27:11 +0200 Subject: [PATCH 020/157] Coding Standards fix --- test/libp2p/capability.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/test/libp2p/capability.cpp b/test/libp2p/capability.cpp index 2f1509e80..e4d0d910c 100644 --- a/test/libp2p/capability.cpp +++ b/test/libp2p/capability.cpp @@ -40,9 +40,10 @@ struct P2PFixture struct VerbosityHolder { - int oldLogVerbosity; VerbosityHolder(): oldLogVerbosity(g_logVerbosity) { g_logVerbosity = 10; } ~VerbosityHolder() { g_logVerbosity = oldLogVerbosity; } + + int oldLogVerbosity; }; class TestCapability: public Capability @@ -122,16 +123,14 @@ BOOST_AUTO_TEST_CASE(capability) int const step = 10; - for (int i = 0; i < 3000; i += step) - if (!host1.isStarted() || !host2.isStarted()) - this_thread::sleep_for(chrono::milliseconds(step)); + for (int i = 0; i < 3000 && (!host1.isStarted() || !host2.isStarted()); i += step) + this_thread::sleep_for(chrono::milliseconds(step)); BOOST_REQUIRE(host1.isStarted() && host2.isStarted()); host1.requirePeer(host2.id(), NodeIPEndpoint(bi::address::from_string(localhost), prefs2.listenPort, prefs2.listenPort)); - for (int i = 0; i < 3000; i += step) - if (!host1.peerCount() || !host2.peerCount()) - this_thread::sleep_for(chrono::milliseconds(step)); + for (int i = 0; i < 3000 && (!host1.peerCount() || !host2.peerCount()); i += step) + this_thread::sleep_for(chrono::milliseconds(step)); BOOST_REQUIRE(host1.peerCount() > 0 && host2.peerCount() > 0); From 3323ebbd1dcbbb38ba6a86aa5b07c0aed8d6d7d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 11 May 2015 17:40:00 +0200 Subject: [PATCH 021/157] Create symlink to old testeth location to make bildbot happy --- test/CMakeLists.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 39a235c58..bedbe42f3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -95,6 +95,12 @@ if (JSONRPC) target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARIES}) endif() +if (UNIX) # Create symlink to old testeth location to make bildbot happy + add_custom_command(TARGET testeth POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_BINARY_DIR}/bin/testeth ${CMAKE_BINARY_DIR}/test/testeth + ) +endif() + enable_testing() set(CTEST_OUTPUT_ON_FAILURE TRUE) @@ -110,7 +116,6 @@ eth_add_test(ClientBase ) eth_add_test(JsonRpc - ARGS --eth_testfile=BlockTests/bcJS_API_Test + ARGS --eth_testfile=BlockTests/bcJS_API_Test ARGS --eth_testfile=BlockTests/bcValidBlockTest ) - From 6f198955dac792873cc427885ee424c9a4ecb646 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 11 May 2015 19:44:45 +0200 Subject: [PATCH 022/157] Use returning erase variant. --- libevmasm/ControlFlowGraph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevmasm/ControlFlowGraph.cpp b/libevmasm/ControlFlowGraph.cpp index 7ed56ff1a..cc68b2af8 100644 --- a/libevmasm/ControlFlowGraph.cpp +++ b/libevmasm/ControlFlowGraph.cpp @@ -289,7 +289,7 @@ void ControlFlowGraph::gatherKnowledge() // Note that this invalidates some contents of pushedTags for (auto it = m_blocks.begin(); it != m_blocks.end();) if (!it->second.startState) - m_blocks.erase(it++); + it = m_blocks.erase(it); else it++; } From c47fe49f80924e3fd54de006189ad7a515d37859 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Mon, 11 May 2015 22:54:12 +0200 Subject: [PATCH 023/157] Fixed warning: unused parameter --- test/libp2p/capability.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/libp2p/capability.cpp b/test/libp2p/capability.cpp index e4d0d910c..2c158f4d8 100644 --- a/test/libp2p/capability.cpp +++ b/test/libp2p/capability.cpp @@ -68,10 +68,10 @@ protected: bool TestCapability::interpret(unsigned _id, RLP const& _r) { cnote << "Capability::interpret(): custom message received"; - BOOST_ASSERT(_id == UserPacket); ++m_cntReceivedMessages; m_testSum += _r[0].toInt(); - return true; + BOOST_ASSERT(_id == UserPacket); + return (_id == UserPacket); } class TestHostCapability: public HostCapability, public Worker From fc34ceb83fadaf009c3cc9fb5c8b7d0cf18fea53 Mon Sep 17 00:00:00 2001 From: subtly Date: Tue, 12 May 2015 02:03:36 +0200 Subject: [PATCH 024/157] Guard m_node.endpoint access and updates. --- libp2p/Common.h | 1 + libp2p/NodeTable.cpp | 27 ++++++++++++++++----------- libp2p/NodeTable.h | 6 +++--- test/libp2p/net.cpp | 2 +- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/libp2p/Common.h b/libp2p/Common.h index da7558ecb..e70d671b2 100644 --- a/libp2p/Common.h +++ b/libp2p/Common.h @@ -172,6 +172,7 @@ struct NodeIPEndpoint /// Setting true causes isAllowed to return true for all addresses. (Used by test fixtures) static bool test_allowLocal; + NodeIPEndpoint(): address(bi::address()), udpPort(0), tcpPort(0) {} NodeIPEndpoint(bi::address _addr, uint16_t _udp, uint16_t _tcp): address(_addr), udpPort(_udp), tcpPort(_tcp) {} NodeIPEndpoint(RLP const& _r) { interpretRLP(_r); } diff --git a/libp2p/NodeTable.cpp b/libp2p/NodeTable.cpp index e926356b7..bd64d4e5e 100644 --- a/libp2p/NodeTable.cpp +++ b/libp2p/NodeTable.cpp @@ -38,7 +38,7 @@ const char* NodeTableAllDetail::name() { return "=P="; } const char* NodeTableEgress::name() { return ">>P"; } const char* NodeTableIngress::name() { return "< NodeTable::addNode(Node const& _node, NodeRelation _relati { if (_relation == Known) { - shared_ptr ret(new NodeEntry(m_node, _node.id, _node.endpoint)); + shared_ptr ret(new NodeEntry(m_node.id, _node.id, _node.endpoint)); ret->pending = false; DEV_GUARDED(x_nodes) m_nodes[_node.id] = ret; @@ -93,11 +93,10 @@ shared_ptr NodeTable::addNode(Node const& _node, NodeRelation _relati // ping address to recover nodeid if nodeid is empty if (!_node.id) { - clog(NodeTableConnect) << "Sending public key discovery Ping to" << (bi::udp::endpoint)_node.endpoint << "(Advertising:" << (bi::udp::endpoint)m_node.endpoint << ")"; - { - Guard l(x_pubkDiscoverPings); + DEV_GUARDED(x_nodes) + clog(NodeTableConnect) << "Sending public key discovery Ping to" << (bi::udp::endpoint)_node.endpoint << "(Advertising:" << (bi::udp::endpoint)m_node.endpoint << ")"; + DEV_GUARDED(x_pubkDiscoverPings); m_pubkDiscoverPings[_node.endpoint.address] = std::chrono::steady_clock::now(); - } ping(_node.endpoint); return move(shared_ptr()); } @@ -106,7 +105,7 @@ shared_ptr NodeTable::addNode(Node const& _node, NodeRelation _relati if (m_nodes.count(_node.id)) return m_nodes[_node.id]; - shared_ptr ret(new NodeEntry(m_node, _node.id, _node.endpoint)); + shared_ptr ret(new NodeEntry(m_node.id, _node.id, _node.endpoint)); DEV_GUARDED(x_nodes) m_nodes[_node.id] = ret; clog(NodeTableConnect) << "addNode pending for" << _node.endpoint; @@ -290,7 +289,10 @@ vector> NodeTable::nearestNodeEntries(NodeId _target) void NodeTable::ping(NodeIPEndpoint _to) const { - PingNode p(m_node.endpoint, _to); + NodeIPEndpoint src; + DEV_GUARDED(x_nodes) + src = m_node.endpoint; + PingNode p(src, _to); p.sign(m_secret); m_socketPointer->send(p); } @@ -462,9 +464,12 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes } // 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; + DEV_GUARDED(x_nodes) + { + 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; diff --git a/libp2p/NodeTable.h b/libp2p/NodeTable.h index 92bf17f79..1df3c8800 100644 --- a/libp2p/NodeTable.h +++ b/libp2p/NodeTable.h @@ -40,7 +40,7 @@ namespace p2p */ struct NodeEntry: public Node { - NodeEntry(Node _src, Public _pubk, NodeIPEndpoint _gw); + NodeEntry(NodeId const& _src, Public const& _pubk, NodeIPEndpoint const& _gw); unsigned const distance; ///< Node's distance (xor of _src as integer). bool pending = true; ///< Node will be ignored until Pong is received }; @@ -201,7 +201,7 @@ private: void ping(NodeEntry* _n) const; /// Returns center node entry which describes this node and used with dist() to calculate xor metric for node table nodes. - NodeEntry center() const { return NodeEntry(m_node, m_node.publicKey(), m_node.endpoint); } + NodeEntry center() const { return NodeEntry(m_node.id, m_node.publicKey(), m_node.endpoint); } /// Used by asynchronous operations to return NodeEntry which is active and managed by node table. std::shared_ptr nodeEntry(NodeId _id); @@ -245,7 +245,7 @@ private: std::unique_ptr m_nodeEventHandler; ///< Event handler for node events. - Node m_node; ///< This node. + Node m_node; ///< This node. LOCK x_state if endpoint access or mutation is required. Do not modify id. 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. diff --git a/test/libp2p/net.cpp b/test/libp2p/net.cpp index a95e685c7..1cd43b13f 100644 --- a/test/libp2p/net.cpp +++ b/test/libp2p/net.cpp @@ -99,7 +99,7 @@ struct TestNodeTable: public NodeTable // manually add node for test { Guard ln(x_nodes); - shared_ptr node(new NodeEntry(m_node, n.first.pub(), NodeIPEndpoint(ourIp, n.second, n.second))); + shared_ptr node(new NodeEntry(m_node.id, n.first.pub(), NodeIPEndpoint(ourIp, n.second, n.second))); node->pending = false; m_nodes[node->id] = node; } From 03a82e401c8cfe3c16139e6f5830ac74b5cd7ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 12 May 2015 09:37:39 +0200 Subject: [PATCH 025/157] testeth: support for --singletest option with only test name param. --- test/TestHelper.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index e0aad310f..1d7734e35 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -552,6 +552,9 @@ void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _e void userDefinedTest(std::function doTests) { if (!Options::get().singleTest) + return; + + if (Options::get().singleTestFile.empty() || Options::get().singleTestName.empty()) { cnote << "Missing user test specification\nUsage: testeth --singletest \n"; return; @@ -732,11 +735,23 @@ Options::Options() inputLimits = true; bigData = true; } - else if (arg == "--singletest" && i + 2 < argc) + else if (arg == "--singletest" && i + 1 < argc) { singleTest = true; - singleTestFile = argv[i + 1]; - singleTestName = argv[i + 2]; + auto name1 = std::string{argv[i + 1]}; + if (i + 1 < argc) // two params + { + auto name2 = std::string{argv[i + 2]}; + if (name2[0] == '-') // not param, another option + singleTestName = std::move(name1); + else + { + singleTestFile = std::move(name1); + singleTestName = std::move(name2); + } + } + else + singleTestName = std::move(name1); } } } From 129a5d4f050489e559d6c505655eaae8c0eb95e4 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 12 May 2015 09:42:10 +0200 Subject: [PATCH 026/157] add confirmation dialog --- mix/qml/FilesSection.qml | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/mix/qml/FilesSection.qml b/mix/qml/FilesSection.qml index 05ba5f897..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 "." @@ -268,8 +269,7 @@ Rectangle MenuItem { text: qsTr("Delete") onTriggered: { - projectModel.removeDocument(documentId); - wrapperItem.removeDocument(documentId); + deleteConfirmation.open(); } } } @@ -279,11 +279,22 @@ Rectangle MenuItem { text: qsTr("Delete") onTriggered: { - projectModel.removeDocument(documentId); - wrapperItem.removeDocument(documentId); + 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); + } + } } } } From 294a73a4e9f85ae3220c644cd520d9933ebf3966 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 12 May 2015 09:47:55 +0200 Subject: [PATCH 027/157] fixed RUNTIME_OUTPUT_DIRECTORY on osx --- cmake/EthExecutableHelper.cmake | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake index d971a5f92..3dd7fa798 100644 --- a/cmake/EthExecutableHelper.cmake +++ b/cmake/EthExecutableHelper.cmake @@ -88,20 +88,15 @@ macro(eth_install_executable EXECUTABLE) if (APPLE) # First have qt5 install plugins and frameworks add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND ${MACDEPLOYQT_APP} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app -executable=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app/Contents/MacOS/${EXECUTABLE} ${eth_qml_dir} - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - COMMAND sh ${CMAKE_SOURCE_DIR}/macdeployfix.sh ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app/Contents + COMMAND ${MACDEPLOYQT_APP} ${EXECUTABLE}.app -executable=${EXECUTABLE}.app/Contents/MacOS/${EXECUTABLE} ${eth_qml_dir} + WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR} + COMMAND sh ${CMAKE_SOURCE_DIR}/macdeployfix.sh ${EXECUTABLE}.app/Contents ) - get_target_property(TARGET_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE} RUNTIME_OUTPUT_DIRECTORY) - # This tool and next will inspect linked libraries in order to determine which dependencies are required - if (${CMAKE_CFG_INTDIR} STREQUAL ".") - # TODO: This should only happen for GUI application - set(APP_BUNDLE_PATH "${TARGET_RUNTIME_OUTPUT_DIRECTORY}/${EXECUTABLE}.app") - else () - set(APP_BUNDLE_PATH "${TARGET_RUNTIME_OUTPUT_DIRECTORY}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app") - endif () + # TODO: This should only happen for GUI application + set(APP_BUNDLE_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INDIR}/${EXECUTABLE}.app") + # This tool and next will inspect linked libraries in order to determine which dependencies are required install(CODE " include(BundleUtilities) set(BU_CHMOD_BUNDLE_ITEMS 1) From 9ea0bf5ab1d8c6146377b9fd3d3642c5d176f698 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 12 May 2015 10:46:04 +0200 Subject: [PATCH 028/157] std::pair instead of QString manipulation --- mix/ClientModel.cpp | 78 +++++++++++++++++---------------- mix/ClientModel.h | 16 ++++--- mix/qml/StateListModel.qml | 9 +++- mix/qml/TransactionDialog.qml | 11 +++-- mix/qml/js/TransactionHelper.js | 3 +- 5 files changed, 67 insertions(+), 50 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 5f6a6c26c..bbb9b109b 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -193,7 +193,7 @@ QVariantMap ClientModel::contractAddresses() const { QVariantMap res; for (auto const& c: m_contractAddresses) - res.insert(c.first, QString::fromStdString(toJS(c.second))); + res.insert(c.first.first, QString::fromStdString(toJS(c.second))); return res; } @@ -257,6 +257,7 @@ void ClientModel::setupState(QVariantMap _state) QString sender = transaction.value("sender").toString(); bool isStdContract = transaction.value("stdContract").toBool(); bool isContractCreation = transaction.value("isContractCreation").toBool(); + bool isFunctionCall = transaction.value("isFunctionCall").toBool(); if (isStdContract) { if (contractId.isEmpty()) //TODO: This is to support old project files, remove later @@ -272,7 +273,7 @@ void ClientModel::setupState(QVariantMap _state) { if (contractId.isEmpty() && m_codeModel->hasContract()) //TODO: This is to support old project files, remove later contractId = m_codeModel->contracts().keys()[0]; - TransactionSettings transactionSettings(contractId, functionId, value, gas, gasAuto, gasPrice, Secret(sender.toStdString()), isContractCreation); + TransactionSettings transactionSettings(contractId, functionId, value, gas, gasAuto, gasPrice, Secret(sender.toStdString()), isContractCreation, isFunctionCall); transactionSettings.parameterValues = transaction.value("parameters").toMap(); if (contractId == functionId || functionId == "Constructor") @@ -308,9 +309,9 @@ void ClientModel::executeSequence(vector const& _sequence, m_gasCosts.clear(); for (TransactionSettings const& transaction: _sequence) { - QString contractName = resolveContractName(transaction.contractId); - QString address = resolveToken(transaction.contractId, deployedContracts); - if (transaction.functionId == "(transfert)") + std::pair ctrInstance = resolvePair(transaction.contractId); + QString address = resolveToken(ctrInstance, deployedContracts); + if (transaction.isFunctionCall) { callAddress(Address(address.toStdString()), bytes(), transaction); onNewTransaction(); @@ -331,7 +332,7 @@ void ClientModel::executeSequence(vector const& _sequence, else { //encode data - CompiledContract const& compilerRes = m_codeModel->contract(contractName); + CompiledContract const& compilerRes = m_codeModel->contract(ctrInstance.first); QFunctionDefinition const* f = nullptr; bytes contractCode = compilerRes.bytes(); shared_ptr contractDef = compilerRes.sharedContract(); @@ -358,29 +359,28 @@ void ClientModel::executeSequence(vector const& _sequence, QSolidityType const* type = p->type(); QVariant value = transaction.parameterValues.value(p->name()); if (type->type().type == SolidityType::Type::Address) - value = QVariant(resolveToken(value.toString(), deployedContracts)); + { + std::pair ctrParamInstance = resolvePair(value.toString()); + value = QVariant(resolveToken(ctrParamInstance, deployedContracts)); + } encoder.encode(value, type->type()); } - if (transaction.functionId.isEmpty() || transaction.functionId == contractName) + if (transaction.functionId.isEmpty() || transaction.functionId == ctrInstance.first) { bytes param = encoder.encodedData(); contractCode.insert(contractCode.end(), param.begin(), param.end()); Address newAddress = deployContract(contractCode, transaction); deployedContracts.push_back(newAddress); - auto contractAddressIter = m_contractAddresses.find(transaction.contractId); - if (contractAddressIter == m_contractAddresses.end() || newAddress != contractAddressIter->second) - { - QString contractToken = retrieveToken(transaction.contractId, deployedContracts); - m_contractAddresses[contractToken] = newAddress; - m_contractNames[newAddress] = contractToken; - contractAddressesChanged(); - } + std::pair contractToken = retrieveToken(transaction.contractId, deployedContracts); + m_contractAddresses[contractToken] = newAddress; + m_contractNames[newAddress] = contractToken.first; + contractAddressesChanged(); gasCostsChanged(); } else { - auto contractAddressIter = m_contractAddresses.find(retrieveToken(transaction.contractId, deployedContracts)); + auto contractAddressIter = m_contractAddresses.find(ctrInstance); if (contractAddressIter == m_contractAddresses.end()) { emit runFailed("Contract '" + transaction.contractId + tr(" not deployed.") + "' " + tr(" Cannot call ") + transaction.functionId); @@ -412,31 +412,35 @@ void ClientModel::executeSequence(vector const& _sequence, }); } -QString ClientModel::resolveToken(QString const& _value, vector
const& _contracts) + +std::pair ClientModel::resolvePair(QString const& _contractId) { - QString ret = _value; - if (_value.startsWith("<") && _value.endsWith(">")) - { - QStringList nb = ret.remove("<").remove(">").split(" - "); - ret = QString::fromStdString("0x" + dev::toHex(_contracts.at(nb.back().toInt()).ref())); - } - return ret; + std::pair ret; + ret.first = _contractId; + ret.second = -1; + if (_contractId.startsWith("<") && _contractId.endsWith(">")) + { + QStringList values = ret.first.remove("<").remove(">").split(" - "); + ret.first = values[0]; + ret.second = values[1].toUInt(); + } + return ret; } -QString ClientModel::retrieveToken(QString const& _value, vector
const& _contracts) +QString ClientModel::resolveToken(std::pair const& _value, vector
const& _contracts) { - QString ret = _value; - if (!_value.startsWith("<") && !_value.endsWith(">")) - return "<" + _value + " - " + QString::number(_contracts.size() - 1) + ">"; - return ret; + if (_value.second != -1) + return QString::fromStdString("0x" + dev::toHex(_contracts.at(_value.second).ref())); + else + return _value.first; } -QString ClientModel::resolveContractName(QString const& _value) +std::pair ClientModel::retrieveToken(QString const& _value, vector
const& _contracts) { - QString ret = _value; - if (_value.startsWith("<") && _value.endsWith(">")) - ret = ret.remove("<").remove(">").split(" - ").first(); - return ret; + std::pair ret; + ret.first = _value; + ret.second = _contracts.size() - 1; + return ret; } void ClientModel::showDebugger() @@ -462,7 +466,7 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t) //try to resolve contract for source level debugging auto nameIter = m_contractNames.find(code.address); CompiledContract const* compilerRes = nullptr; - if (nameIter != m_contractNames.end() && (compilerRes = m_codeModel->tryGetContract(resolveContractName(nameIter->second)))) //returned object is guaranteed to live till the end of event handler in main thread + if (nameIter != m_contractNames.end() && (compilerRes = m_codeModel->tryGetContract(nameIter->second))) //returned object is guaranteed to live till the end of event handler in main thread { eth::AssemblyItems assemblyItems = !_t.isConstructor() ? compilerRes->assemblyItems() : compilerRes->constructorAssemblyItems(); codes.back()->setDocument(compilerRes->documentId()); @@ -723,7 +727,7 @@ void ClientModel::onNewTransaction() auto contractAddressIter = m_contractNames.find(contractAddress); if (contractAddressIter != m_contractNames.end()) { - CompiledContract const& compilerRes = m_codeModel->contract(resolveContractName(contractAddressIter->second)); + CompiledContract const& compilerRes = m_codeModel->contract(contractAddressIter->second); const QContractDefinition* def = compilerRes.contract(); contract = def->name(); if (abi) diff --git a/mix/ClientModel.h b/mix/ClientModel.h index a9cf89018..9d4168995 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -53,10 +53,10 @@ struct SolidityType; struct TransactionSettings { TransactionSettings() {} - TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, bool _gasAuto, u256 _gasPrice, Secret _sender, int _isContractCreation): - contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasAuto(_gasAuto), gasPrice(_gasPrice), sender(_sender), isContractCreation(_isContractCreation) {} + TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, bool _gasAuto, u256 _gasPrice, Secret _sender, bool _isContractCreation, bool _isFunctionCall): + contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasAuto(_gasAuto), gasPrice(_gasPrice), sender(_sender), isContractCreation(_isContractCreation), isFunctionCall(_isFunctionCall) {} TransactionSettings(QString const& _stdContractName, QString const& _stdContractUrl): - contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl), isContractCreation(true) {} + contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl), isContractCreation(true), isFunctionCall(false) {} /// Contract name QString contractId; @@ -78,6 +78,8 @@ struct TransactionSettings Secret sender; /// Tr deploys a contract bool isContractCreation; + /// Tr call a ctr function + bool isFunctionCall; }; @@ -229,9 +231,9 @@ private: void onStateReset(); void showDebuggerForTransaction(ExecutionResult const& _t); QVariant formatValue(SolidityType const& _type, dev::u256 const& _value); - QString resolveToken(QString const& _value, std::vector
const& _contracts); - QString resolveContractName(QString const& _value); - QString retrieveToken(QString const& _value, std::vector
const& _contracts); + QString resolveToken(std::pair const& _value, std::vector
const& _contracts); + std::pair retrieveToken(QString const& _value, std::vector
const& _contracts); + std::pair resolvePair(QString const& _contractId); QVariant formatStorageValue(SolidityType const& _type, std::unordered_map const& _storage, unsigned _offset, dev::u256 const& _slot); std::atomic m_running; @@ -241,7 +243,7 @@ private: std::unique_ptr m_rpcConnector; std::unique_ptr m_web3Server; QList m_gasCosts; - std::map m_contractAddresses; + std::map, Address> m_contractAddresses; std::map m_contractNames; std::map m_stdContractAddresses; std::map m_stdContractNames; diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index b4eed525d..b4d9b6bc6 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -58,9 +58,13 @@ Item { parameters: {}, sender: t.sender, isContractCreation: t.isContractCreation, - label: t.label + label: t.label, + isFunctionCall: t.isFunctionCall }; + if (r.isFunctionCall === undefined) + r.isFunctionCall = true; + if (!r.label) r.label = r.contractId + " - " + r.functionId; @@ -122,7 +126,8 @@ Item { sender: t.sender, parameters: {}, isContractCreation: t.isContractCreation, - label: t.label + label: t.label, + isFunctionCall: t.isFunctionCall }; for (var key in t.parameters) r.parameters[key] = t.parameters[key]; diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index d26fbaf5a..7c9b28aa7 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -87,8 +87,6 @@ Dialog { else loadParameters(); - - visible = true; valueField.focus = true; } @@ -212,12 +210,19 @@ Dialog { } item.isContractCreation = trType.checked; + + if (item.functionId === "(transfert)") + item.isFunctionCall = false; + if (!item.isContractCreation) { item.contractId = recipients.currentText; item.label = item.contractId + " " + item.functionId; if (recipients.current().type === "address") - item.functionId = "(transfert)"; + { + item.functionId = ""; + item.isFunctionCall = false; + } } else { diff --git a/mix/qml/js/TransactionHelper.js b/mix/qml/js/TransactionHelper.js index 33072fdba..b9a011b66 100644 --- a/mix/qml/js/TransactionHelper.js +++ b/mix/qml/js/TransactionHelper.js @@ -11,7 +11,8 @@ function defaultTransaction() parameters: {}, stdContract: false, isContractCreation: true, - label: "" + label: "", + isFunctionCall: true }; } From d969e109bb92f1f4829f2d7a39c80137ef1c30e7 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 12 May 2015 12:21:26 +0300 Subject: [PATCH 029/157] Fix braces. --- libethcore/EthashAux.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libethcore/EthashAux.h b/libethcore/EthashAux.h index c90ee048e..8788acc83 100644 --- a/libethcore/EthashAux.h +++ b/libethcore/EthashAux.h @@ -24,7 +24,8 @@ namespace dev { -namespace eth{ +namespace eth +{ class EthashAux { From e8f7c26479d4f5d633012a82a53afd3cfa772f7b Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 12 May 2015 11:25:34 +0200 Subject: [PATCH 030/157] Fixed template problem. --- libevmasm/KnownState.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index d6fbde2d9..5a70a74fb 100644 --- a/libevmasm/KnownState.cpp +++ b/libevmasm/KnownState.cpp @@ -162,7 +162,7 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool /// Helper function for KnownState::reduceToCommonKnowledge, removes everything from /// _this which is not in or not equal to the value in _other. -template void intersect( +template void intersect( _Mapping& _this, _Mapping const& _other, function<_KeyType(_KeyType)> const& _keyTrans = [](_KeyType _k) { return _k; } @@ -175,6 +175,11 @@ template void intersect it = _this.erase(it); } +template void intersect(_Mapping& _this, _Mapping const& _other) +{ + intersect<_Mapping, ExpressionClasses::Id>(_this, _other, [](ExpressionClasses::Id _k) { return _k; }); +} + void KnownState::reduceToCommonKnowledge(KnownState const& _other) { int stackDiff = m_stackHeight - _other.m_stackHeight; From 40de803f66f35ecd5a4636effd04b5d1662a3f3d Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 12 May 2015 11:39:31 +0200 Subject: [PATCH 031/157] bug fix --- mix/ClientModel.cpp | 2 +- mix/ClientModel.h | 2 +- mix/qml/TransactionDialog.qml | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index dc9346d3e..fc8ce4c33 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -312,7 +312,7 @@ void ClientModel::executeSequence(vector const& _sequence, { std::pair ctrInstance = resolvePair(transaction.contractId); QString address = resolveToken(ctrInstance, deployedContracts); - if (transaction.isFunctionCall) + if (!transaction.isFunctionCall) { callAddress(Address(address.toStdString()), bytes(), transaction); onNewTransaction(); diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 2ca3d2c69..e1648b78d 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -56,7 +56,7 @@ struct TransactionSettings TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, bool _gasAuto, u256 _gasPrice, Secret _sender, bool _isContractCreation, bool _isFunctionCall): contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasAuto(_gasAuto), gasPrice(_gasPrice), sender(_sender), isContractCreation(_isContractCreation), isFunctionCall(_isFunctionCall) {} TransactionSettings(QString const& _stdContractName, QString const& _stdContractUrl): - contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl), isContractCreation(true), isFunctionCall(false) {} + contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl), isContractCreation(true), isFunctionCall(true) {} /// Contract name QString contractId; diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 7c9b28aa7..d9c811704 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -210,9 +210,7 @@ Dialog { } item.isContractCreation = trType.checked; - - if (item.functionId === "(transfert)") - item.isFunctionCall = false; + item.isFunctionCall = item.functionId !== "(transfert)"; if (!item.isContractCreation) { From 2eed2ca5e0910a2d1412fb9e938b9c8778db025b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 12 May 2015 12:55:40 +0300 Subject: [PATCH 032/157] Refactored much EthashAux., especially the DAG generation callback stuff. Made m_epochs active again. --- libethcore/EthashAux.cpp | 49 ++++++++++++++++++++++++++++++---------- libethcore/EthashAux.h | 11 +++++---- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index 210f70c78..7bcb976d6 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -41,6 +41,8 @@ using namespace chrono; using namespace dev; using namespace eth; +const char* DAGChannel::name() { return EthGreen "DAG"; } + EthashAux* dev::eth::EthashAux::s_this = nullptr; EthashAux::~EthashAux() @@ -76,9 +78,30 @@ h256 EthashAux::seedHash(unsigned _number) return get()->m_seedHashes[epoch]; } +uint64_t EthashAux::number(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 epoch * ETHASH_EPOCH_LENGTH; +} + void EthashAux::killCache(h256 const& _s) { - RecursiveGuard l(x_this); + RecursiveGuard l(x_lights); m_lights.erase(_s); } @@ -89,7 +112,7 @@ EthashAux::LightType EthashAux::light(BlockInfo const& _header) EthashAux::LightType EthashAux::light(uint64_t _blockNumber) { - RecursiveGuard l(get()->x_this); + RecursiveGuard l(get()->x_lights); h256 seedHash = EthashAux::seedHash(_blockNumber); LightType ret = get()->m_lights[seedHash]; return ret ? ret : (get()->m_lights[seedHash] = make_shared(_blockNumber)); @@ -126,30 +149,32 @@ bytesConstRef EthashAux::FullAllocation::data() const return bytesConstRef((byte const*)ethash_full_dag(full), size()); } -EthashAux::FullType EthashAux::full(BlockInfo const& _header) +EthashAux::FullType EthashAux::full(BlockInfo const& _header, function const& _f) { - return full((uint64_t) _header.number); + return full((uint64_t)_header.number, _f); } -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) +static std::function s_dagCallback; +static int dagCallbackShim(unsigned _p) { - clog(DAGChannel) << "Generating DAG file. Progress: " << toString(_progress) << "%"; - return 0; + clog(DAGChannel) << "Generating DAG file. Progress: " << toString(_p) << "%"; + return s_dagCallback ? s_dagCallback(_p) : 0; } -EthashAux::FullType EthashAux::full(uint64_t _blockNumber) +EthashAux::FullType EthashAux::full(uint64_t _blockNumber, function const& _f) { - RecursiveGuard l(get()->x_this); + auto l = light(_blockNumber); h256 seedHash = EthashAux::seedHash(_blockNumber); FullType ret; + + Guard lock(get()->x_fulls); if ((ret = get()->m_fulls[seedHash].lock())) { get()->m_lastUsedFull = ret; return ret; } - ret = get()->m_lastUsedFull = make_shared(light(_blockNumber)->light, ethash_callback); + s_dagCallback = _f; + ret = get()->m_lastUsedFull = make_shared(l->light, dagCallbackShim); get()->m_fulls[seedHash] = ret; return ret; } diff --git a/libethcore/EthashAux.h b/libethcore/EthashAux.h index bc9361db7..dbfe54d43 100644 --- a/libethcore/EthashAux.h +++ b/libethcore/EthashAux.h @@ -27,6 +27,7 @@ namespace dev namespace eth { +struct DAGChannel: public LogChannel { static const char* name(); static const int verbosity = 1; }; class EthashAux { @@ -59,27 +60,29 @@ public: using FullType = std::shared_ptr; static h256 seedHash(unsigned _number); + static uint64_t number(h256 const& _seedHash); static uint64_t cacheSize(BlockInfo const& _header); static LightType light(BlockInfo const& _header); static LightType light(uint64_t _blockNumber); - static FullType full(BlockInfo const& _header); - static FullType full(uint64_t _blockNumber); + static FullType full(BlockInfo const& _header, std::function const& _f = std::function()); + static FullType full(uint64_t _blockNumber, std::function const& _f = std::function()); 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(uint64_t _blockNumber, h256 const& _headerHash, Nonce const& _nonce); - private: EthashAux() {} void killCache(h256 const& _s); static EthashAux* s_this; - RecursiveMutex x_this; + RecursiveMutex x_lights; std::unordered_map> m_lights; + + Mutex x_fulls; std::unordered_map> m_fulls; FullType m_lastUsedFull; From 3a81c1059846a93e1d46d843b319260c6b19b95e Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 12 May 2015 12:14:26 +0200 Subject: [PATCH 033/157] use - instead of "(transfer)" --- mix/qml/TransactionDialog.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index d9c811704..fe4bfc82e 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -107,6 +107,7 @@ Dialog { function loadFunctions(contractId) { functionsModel.clear(); + functionsModel.append({ text: " - " }); var contract = codeModel.contracts[contractId]; if (contract) { var functions = codeModel.contracts[contractId].contract.functions; @@ -114,7 +115,6 @@ Dialog { functionsModel.append({ text: functions[f].name }); } } - functionsModel.append({ text: "(transfert)" }); } function selectContract(contractName) @@ -210,7 +210,7 @@ Dialog { } item.isContractCreation = trType.checked; - item.isFunctionCall = item.functionId !== "(transfert)"; + item.isFunctionCall = item.functionId !== " - "; if (!item.isContractCreation) { From 6b74a4e96f03c0a6195a0954151a3a2c2a5bdda6 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 12 May 2015 12:42:29 +0200 Subject: [PATCH 034/157] Recover lost code after ethash merge - Recover installing ethash if ethash-cl is not built --- libethash/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libethash/CMakeLists.txt b/libethash/CMakeLists.txt index a65621c3e..907eccd40 100644 --- a/libethash/CMakeLists.txt +++ b/libethash/CMakeLists.txt @@ -42,3 +42,7 @@ add_library(${LIBRARY} ${FILES}) if (CRYPTOPP_FOUND) TARGET_LINK_LIBRARIES(${LIBRARY} ${CRYPTOPP_LIBRARIES}) endif() + +if (NOT ETHASHCL) + install( TARGETS ${LIBRARY} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +endif () \ No newline at end of file From da1fcbb19b4e07e9d40f1d29de0b190100f7e9d1 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 12 May 2015 16:46:42 +0300 Subject: [PATCH 035/157] DAG generation improvements. Generate next DAG in AZ! Cleanups to Ethash & Aux. DAG Progress in AZ. --- alethzero/Main.ui | 6 +++ alethzero/MainWin.cpp | 39 +++++++++----- alethzero/MainWin.h | 1 + alethzero/Transact.cpp | 5 +- eth/main.cpp | 107 ++++++++++++++++++++++----------------- libdevcore/Common.h | 8 +-- libdevcore/Worker.cpp | 10 ++-- libethcore/Ethash.cpp | 6 ++- libethcore/Ethash.h | 2 +- libethcore/EthashAux.cpp | 46 ++++++++++++----- libethcore/EthashAux.h | 14 ++++- libethereum/ClientBase.h | 4 +- libethereum/State.cpp | 4 +- 13 files changed, 161 insertions(+), 91 deletions(-) diff --git a/alethzero/Main.ui b/alethzero/Main.ui index 5b0ad7582..e0852142a 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -151,6 +151,7 @@ + @@ -1727,6 +1728,11 @@ font-size: 14pt In&ject Block + + + Prepare Next &DAG + + diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 87c9c2dc9..7551eaa35 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -204,7 +204,7 @@ Main::Main(QWidget *parent) : 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_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(), this)); @@ -943,22 +943,30 @@ void Main::on_preview_triggered() refreshAll(); } +void Main::on_prepNextDAG_triggered() +{ + EthashAux::computeFull(ethereum()->blockChain().number() + ETHASH_EPOCH_LENGTH); +} + void Main::refreshMining() { + pair gp = EthashAux::fullGeneratingProgress(); + QString t; + if (gp.first != EthashAux::NotGenerating) + t = QString("DAG for #%1-#%2: %3% complete; ").arg(gp.first).arg(gp.first + ETHASH_EPOCH_LENGTH - 1).arg(gp.second); MiningProgress p = ethereum()->miningProgress(); - ui->mineStatus->setText(ethereum()->isMining() ? QString("%1s @ %2kH/s").arg(p.ms / 1000).arg(p.ms ? p.hashes / p.ms : 0) : "Not mining"); - if (!ui->miningView->isVisible()) - return; - list l = ethereum()->miningHistory(); - static unsigned lh = 0; - if (p.hashes < lh) - ui->miningView->resetStats(); - lh = p.hashes; - ui->miningView->appendStats(l, p); -/* if (p.ms) - for (MineInfo const& i: l) - cnote << i.hashes * 10 << "h/sec, need:" << i.requirement << " best:" << i.best << " best-so-far:" << p.best << " avg-speed:" << (p.hashes * 1000 / p.ms) << "h/sec"; -*/ + ui->mineStatus->setText(t + (ethereum()->isMining() ? p.hashes > 0 ? QString("%1s @ %2kH/s").arg(p.ms / 1000).arg(p.ms ? p.hashes / p.ms : 0) : "Awaiting DAG" : "Not mining")); + if (ethereum()->isMining() && p.hashes > 0) + { + if (!ui->miningView->isVisible()) + return; + list l = ethereum()->miningHistory(); + static unsigned lh = 0; + if (p.hashes < lh) + ui->miningView->resetStats(); + lh = p.hashes; + ui->miningView->appendStats(l, p); + } } void Main::setBeneficiary(Address const& _b) @@ -1878,6 +1886,7 @@ void Main::on_mine_triggered() { if (ui->mine->isChecked()) { +// EthashAux::computeFull(ethereum()->blockChain().number()); ethereum()->setAddress(m_beneficiary); ethereum()->startMining(); } @@ -2027,6 +2036,7 @@ std::string Main::prettyU256(dev::u256 const& _n) const void Main::on_post_clicked() { + return; shh::Message m; m.setTo(stringToPublic(ui->shhTo->currentText())); m.setPayload(parseData(ui->shhData->toPlainText().toStdString())); @@ -2051,6 +2061,7 @@ int Main::authenticate(QString _title, QString _text) void Main::refreshWhispers() { + return; ui->whispers->clear(); for (auto const& w: whisper()->all()) { diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 51d4cc8f4..d9075d178 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -124,6 +124,7 @@ private slots: // Mining void on_mine_triggered(); + void on_prepNextDAG_triggered(); // View void on_refresh_triggered(); diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index bc37db8ef..f2a8ef0d5 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -299,8 +299,9 @@ void Transact::rejigData() return; // Determine how much balance we have to play with... - auto s = findSecret(value() + ethereum()->gasLimitRemaining() * gasPrice()); - auto b = ethereum()->balanceAt(KeyPair(s).address(), PendingBlock); + //findSecret(value() + ethereum()->gasLimitRemaining() * gasPrice()); + auto s = fromAccount(); + auto b = ethereum()->balanceAt(s, PendingBlock); m_allGood = true; QString htmlInfo; diff --git a/eth/main.cpp b/eth/main.cpp index d6582e4d3..abb78c20d 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -158,6 +158,11 @@ void help() << " --port Connect to remote port (default: 30303)." << endl << " --network-id Only connect to other hosts with this network id (default:0)." << endl << " --upnp Use UPnP for NAT (default: on)." << endl + << endl + << "Client structured logging:" << endl + << " --structured-logging Enable structured logging (default output to stdout)." << endl + << " --structured-logging-format Set the structured logging time format." << endl + << " --structured-logging-url Set the structured logging destination (currently only file:// supported)." << endl #if ETH_JSONRPC || !ETH_TRUE << endl << "Work farming mode:" << endl @@ -806,8 +811,11 @@ int main(int argc, char** argv) structuredLoggingFormat = string(argv[++i]); else if (arg == "--structured-logging") structuredLogging = true; - else if (arg == "--structured-logging-destination" && i + 1 < argc) + else if (arg == "--structured-logging-url" && i + 1 < argc) + { + structuredLogging = true; 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) @@ -1033,6 +1041,28 @@ int main(int argc, char** argv) if (!clientName.empty()) clientName += "/"; + 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; + }; + + auto getPassword = [&](string const& prompt){ + auto s = silence; + silence = true; + cout << endl; + string ret = dev::getPassword(prompt); + silence = s; + return ret; + }; + auto getAccountPassword = [&](Address const& a){ + return getPassword("Enter password for address " + keyManager.accountDetails()[a].first + " (" + a.abridged() + "; hint:" + keyManager.accountDetails()[a].second + "): "); + }; + 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); @@ -1042,13 +1072,38 @@ int main(int argc, char** argv) clientImplString, dbPath, killChain, - nodeMode == NodeMode::Full ? set{"eth", "shh"} : set(), + nodeMode == NodeMode::Full ? set{"eth"/*, "shh"*/} : set(), netPrefs, &nodesState); if (mode == OperationMode::DAGInit) doInitDAG(web3.ethereum()->blockChain().number() + (initDAG == PendingBlock ? 30000 : 0)); + 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); + } + auto toNumber = [&](string const& s) -> unsigned { if (s == "latest") return web3.ethereum()->number(); @@ -1137,53 +1192,13 @@ int main(int argc, char** argv) if (remoteHost.size()) web3.addNode(p2p::NodeId(), remoteHost + ":" + toString(remotePort)); - 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, make_shared([&](){return web3.ethereum();}, getPassword, keyManager), vector())); + jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared([&](){return web3.ethereum();}, getAccountPassword, keyManager), vector())); jsonrpcServer->StartListening(); } #endif @@ -1327,7 +1342,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, make_shared([&](){return web3.ethereum();}, getPassword, keyManager), vector())); + jsonrpcServer = shared_ptr(new WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared([&](){return web3.ethereum();}, getAccountPassword, keyManager), vector())); jsonrpcServer->StartListening(); } else if (cmd == "jsonstop") @@ -1479,7 +1494,7 @@ int main(int argc, char** argv) try { Address dest = h160(fromHex(hexAddr, WhenError::Throw)); - c->submitTransaction(keyManager.secret(signingKey, [&](){ return getPassword(signingKey); }), amount, dest, bytes(), minGas); + c->submitTransaction(keyManager.secret(signingKey, [&](){ return getAccountPassword(signingKey); }), amount, dest, bytes(), minGas); } catch (BadHexCharacter& _e) { @@ -1548,7 +1563,7 @@ int main(int argc, char** argv) else if (gas < minGas) cwarn << "Minimum gas amount is" << minGas; else - c->submitTransaction(keyManager.secret(signingKey, [&](){ return getPassword(signingKey); }), endowment, init, gas, gasPrice); + c->submitTransaction(keyManager.secret(signingKey, [&](){ return getAccountPassword(signingKey); }), endowment, init, gas, gasPrice); } else cwarn << "Require parameters: contract ENDOWMENT GASPRICE GAS CODEHEX"; diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 41f1b1d49..95817e41c 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -199,12 +199,12 @@ private: #define DEV_TIMED_FUNCTION DEV_TIMED_SCOPE(__PRETTY_FUNCTION__) #endif -#define DEV_TIMED_IF(S, MS) for (::std::pair<::dev::TimerHelper, bool> __eth_t(::dev::TimerHelper(#S, MS), true); __eth_t.second; __eth_t.second = false) -#define DEV_TIMED_SCOPE_IF(S) ::dev::TimerHelper __eth_t(S, MS) +#define DEV_TIMED_ABOVE(S, MS) for (::std::pair<::dev::TimerHelper, bool> __eth_t(::dev::TimerHelper(#S, MS), true); __eth_t.second; __eth_t.second = false) +#define DEV_TIMED_SCOPE_ABOVE(S) ::dev::TimerHelper __eth_t(S, MS) #if WIN32 -#define DEV_TIMED_FUNCTION_IF(MS) DEV_TIMED_SCOPE_IF(__FUNCSIG__, MS) +#define DEV_TIMED_FUNCTION_ABOVE(MS) DEV_TIMED_SCOPE_ABOVE(__FUNCSIG__, MS) #else -#define DEV_TIMED_FUNCTION_IF(MS) DEV_TIMED_SCOPE_IF(__PRETTY_FUNCTION__, MS) +#define DEV_TIMED_FUNCTION_ABOVE(MS) DEV_TIMED_SCOPE_ABOVE(__PRETTY_FUNCTION__, MS) #endif enum class WithExisting: int diff --git a/libdevcore/Worker.cpp b/libdevcore/Worker.cpp index 7d790ccf6..ab19b2f74 100644 --- a/libdevcore/Worker.cpp +++ b/libdevcore/Worker.cpp @@ -65,15 +65,15 @@ void Worker::startWorking() m_state.exchange(ex); // cnote << "Waiting until not Stopped..."; - DEV_TIMED_IF(Worker stopping, 100) + DEV_TIMED_ABOVE(Worker stopping, 100) while (m_state == WorkerState::Stopped) this_thread::sleep_for(chrono::milliseconds(20)); } })); // cnote << "Spawning" << m_name; } - DEV_TIMED_IF(Start worker, 100) - while (m_state != WorkerState::Started) + DEV_TIMED_ABOVE(Start worker, 100) + while (m_state == WorkerState::Starting) this_thread::sleep_for(chrono::microseconds(20)); } @@ -85,7 +85,7 @@ void Worker::stopWorking() WorkerState ex = WorkerState::Started; m_state.compare_exchange_strong(ex, WorkerState::Stopping); - DEV_TIMED_IF(Stop worker, 100) + DEV_TIMED_ABOVE(Stop worker, 100) while (m_state != WorkerState::Stopped) this_thread::sleep_for(chrono::microseconds(20)); } @@ -99,7 +99,7 @@ void Worker::terminate() { m_state.exchange(WorkerState::Killing); - DEV_TIMED_IF(Terminate worker, 100) + DEV_TIMED_ABOVE(Terminate worker, 100) m_work->join(); m_work.reset(); diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index db1a17b0a..3724d8255 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -76,9 +76,9 @@ Ethash::WorkPackage Ethash::package(BlockInfo const& _bi) return ret; } -void Ethash::prep(BlockInfo const& _header) +void Ethash::prep(BlockInfo const& _header, std::function const& _f) { - EthashAux::full(_header); + EthashAux::full((unsigned)_header.number, _f); } bool Ethash::preVerify(BlockInfo const& _header) @@ -310,6 +310,8 @@ void Ethash::GPUMiner::workLoop() unsigned device = instances() > 1 ? index() : s_deviceId; + if (!EthashAux::computeFull(w.blockNumber)) + return; EthashAux::FullType dag = EthashAux::full(w.blockNumber); bytesConstRef dagData = dag->data(); m_miner->init(dagData.data(), dagData.size(), 32, s_platformId, device); diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 1fcab55de..82db15e87 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -74,7 +74,7 @@ public: static std::string name(); static unsigned revision(); - static void prep(BlockInfo const& _header); + static void prep(BlockInfo const& _header, std::function const& _f = std::function()); static bool verify(BlockInfo const& _header); static bool preVerify(BlockInfo const& _header); static WorkPackage package(BlockInfo const& _header); diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index 7bcb976d6..f7a0ac41d 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -149,11 +149,6 @@ bytesConstRef EthashAux::FullAllocation::data() const return bytesConstRef((byte const*)ethash_full_dag(full), size()); } -EthashAux::FullType EthashAux::full(BlockInfo const& _header, function const& _f) -{ - return full((uint64_t)_header.number, _f); -} - static std::function s_dagCallback; static int dagCallbackShim(unsigned _p) { @@ -167,16 +162,43 @@ EthashAux::FullType EthashAux::full(uint64_t _blockNumber, functionx_fulls); - if ((ret = get()->m_fulls[seedHash].lock())) + DEV_GUARDED(get()->x_fulls) + if ((ret = get()->m_fulls[seedHash].lock())) + { + get()->m_lastUsedFull = ret; + return ret; + } + + s_dagCallback = _f; + ret = make_shared(l->light, dagCallbackShim); + + DEV_GUARDED(get()->x_fulls) + get()->m_fulls[seedHash] = get()->m_lastUsedFull = ret; + return ret; +} + +unsigned EthashAux::computeFull(uint64_t _blockNumber) +{ + Guard l(get()->x_fulls); + h256 seedHash = EthashAux::seedHash(_blockNumber); + if (FullType ret = get()->m_fulls[seedHash].lock()) { get()->m_lastUsedFull = ret; - return ret; + return 100; } - s_dagCallback = _f; - ret = get()->m_lastUsedFull = make_shared(l->light, dagCallbackShim); - get()->m_fulls[seedHash] = ret; - return ret; + + if (!get()->m_fullGenerator || !get()->m_fullGenerator->joinable()) + { + get()->m_fullProgress = 0; + get()->m_generatingFullNumber = _blockNumber / ETHASH_EPOCH_LENGTH * ETHASH_EPOCH_LENGTH; + get()->m_fullGenerator = unique_ptr(new thread([=](){ + get()->full(_blockNumber, [](unsigned p){ get()->m_fullProgress = p; return 0; }); + get()->m_fullProgress = 0; + get()->m_generatingFullNumber = NotGenerating; + })); + } + + return (get()->m_generatingFullNumber == _blockNumber) ? get()->m_fullProgress : 0; } Ethash::Result EthashAux::FullAllocation::compute(h256 const& _headerHash, Nonce const& _nonce) const diff --git a/libethcore/EthashAux.h b/libethcore/EthashAux.h index dbfe54d43..f57f7a4d3 100644 --- a/libethcore/EthashAux.h +++ b/libethcore/EthashAux.h @@ -19,7 +19,9 @@ * @date 2014 */ +#include #include +#include #include "Ethash.h" namespace dev @@ -65,7 +67,13 @@ public: static LightType light(BlockInfo const& _header); static LightType light(uint64_t _blockNumber); - static FullType full(BlockInfo const& _header, std::function const& _f = std::function()); + + static const uint64_t NotGenerating = (uint64_t)-1; + /// Kicks off generation of DAG for @a _blocknumber and @returns false or @returns true if ready. + static unsigned computeFull(uint64_t _blockNumber); + /// Information on the generation progress. + static std::pair fullGeneratingProgress() { return std::make_pair(get()->m_generatingFullNumber, get()->m_fullProgress); } + /// Kicks off generation of DAG for @a _blocknumber and blocks until ready; @returns result. static FullType full(uint64_t _blockNumber, std::function const& _f = std::function()); static Ethash::Result eval(BlockInfo const& _header) { return eval(_header, _header.nonce); } @@ -83,8 +91,12 @@ private: std::unordered_map> m_lights; Mutex x_fulls; + std::condition_variable m_fullsChanged; std::unordered_map> m_fulls; FullType m_lastUsedFull; + std::unique_ptr m_fullGenerator; + uint64_t m_generatingFullNumber = NotGenerating; + unsigned m_fullProgress; Mutex x_epochs; std::unordered_map m_epochs; diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index 235a6f540..2b271b1df 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -84,11 +84,11 @@ public: using Interface::submitTransaction; /// Makes the given call. Nothing is recorded into the state. - 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; + virtual ExecutionResult call(Address const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) override; using Interface::call; /// Makes the given create. Nothing is recorded into the state. - 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; + virtual ExecutionResult create(Address const& _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) override; using Interface::create; using Interface::balanceAt; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 50e4b26ab..584de461b 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -515,10 +515,10 @@ pair State::sync(BlockChain const& _bc, TransactionQu cnote << i.first << "Dropping old transaction (nonce too low)"; _tq.drop(i.first); } - else if (got > req + 5) + else if (got > req + 25) { // too new - cnote << i.first << "Dropping new transaction (> 5 nonces ahead)"; + cnote << i.first << "Dropping new transaction (> 25 nonces ahead)"; _tq.drop(i.first); } else From 0315689bb37f63c714abc6194a29f8312e6f9e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 12 May 2015 16:14:18 +0200 Subject: [PATCH 036/157] Ping buildbot --- test/libevm/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libevm/vm.cpp b/test/libevm/vm.cpp index 2d67d7670..f9aac2eb2 100644 --- a/test/libevm/vm.cpp +++ b/test/libevm/vm.cpp @@ -432,7 +432,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) } } -} } // Namespace Close +} } // namespace close BOOST_AUTO_TEST_SUITE(VMTests) From 212a01136bd28d0f53cab2e07c018ae888977377 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 12 May 2015 16:16:44 +0200 Subject: [PATCH 037/157] Unify blocks with shared code. --- libevmasm/Assembly.cpp | 10 +++ libevmasm/AssemblyItem.h | 2 + libevmasm/BlockDeduplicator.cpp | 93 ++++++++++++++++++++++++++ libevmasm/BlockDeduplicator.h | 69 +++++++++++++++++++ test/libsolidity/SolidityOptimizer.cpp | 38 ++++++++++- 5 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 libevmasm/BlockDeduplicator.cpp create mode 100644 libevmasm/BlockDeduplicator.h diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index abcd44516..1011392b9 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include using namespace std; using namespace dev; @@ -348,8 +349,17 @@ Assembly& Assembly::optimise(bool _enable) copy(orig, iter, back_inserter(optimisedItems)); } } + if (optimisedItems.size() < m_items.size()) + { m_items = move(optimisedItems); + count++; + } + + // This only modifies PushTags, we have to run again to actually remove code. + BlockDeduplicator dedup(m_items); + if (dedup.deduplicate()) + count++; } } diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 6f2a65de9..b3012a7ea 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -68,6 +68,8 @@ public: /// @returns true iff the type and data of the items are equal. bool operator==(AssemblyItem const& _other) const { return m_type == _other.m_type && m_data == _other.m_data; } bool operator!=(AssemblyItem const& _other) const { return !operator==(_other); } + /// Less-than operator compatible with operator==. + bool operator<(AssemblyItem const& _other) const { return std::tie(m_type, m_data) < std::tie(_other.m_type, _other.m_data); } /// @returns an upper bound for the number of bytes required by this item, assuming that /// the value of a jump tag takes @a _addressLength bytes. diff --git a/libevmasm/BlockDeduplicator.cpp b/libevmasm/BlockDeduplicator.cpp new file mode 100644 index 000000000..ca4f7e21a --- /dev/null +++ b/libevmasm/BlockDeduplicator.cpp @@ -0,0 +1,93 @@ +/* + 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 BlockDeduplicator.cpp + * @author Christian + * @date 2015 + * Unifies basic blocks that share content. + */ + +#include +#include +#include +#include + +#include + +using namespace std; +using namespace dev; +using namespace dev::eth; + + +bool BlockDeduplicator::deduplicate() +{ + // Compares indices based on the suffix that starts there, ignoring tags and stopping at + // opcodes that stop the control flow. + function comparator = [&](size_t _i, size_t _j) + { + if (_i == _j) + return false; + + BlockIterator first(m_items.begin() + _i, m_items.end()); + BlockIterator second(m_items.begin() + _j, m_items.end()); + BlockIterator end(m_items.end(), m_items.end()); + + if (first != end && (*first).type() == Tag) + ++first; + if (second != end && (*second).type() == Tag) + ++second; + + return std::lexicographical_compare(first, end, second, end); + }; + + set> blocksSeen(comparator); + map tagReplacement; + for (size_t i = 0; i < m_items.size(); ++i) + { + if (m_items.at(i).type() != Tag) + continue; + auto it = blocksSeen.find(i); + if (it == blocksSeen.end()) + blocksSeen.insert(i); + else + tagReplacement[m_items.at(i).data()] = m_items.at(*it).data(); + } + + bool ret = false; + for (AssemblyItem& item: m_items) + if (item.type() == PushTag && tagReplacement.count(item.data())) + { + ret = true; + item.setData(tagReplacement.at(item.data())); + } + return ret; +} + +BlockDeduplicator::BlockIterator& BlockDeduplicator::BlockIterator::operator++() +{ + if (it == end) + return *this; + if (SemanticInformation::altersControlFlow(*it) && *it != AssemblyItem(eth::Instruction::JUMPI)) + it = end; + else + { + ++it; + while (it != end && it->type() == Tag) + ++it; + } + return *this; +} diff --git a/libevmasm/BlockDeduplicator.h b/libevmasm/BlockDeduplicator.h new file mode 100644 index 000000000..8a82a1ed7 --- /dev/null +++ b/libevmasm/BlockDeduplicator.h @@ -0,0 +1,69 @@ +/* + 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 BlockDeduplicator.h + * @author Christian + * @date 2015 + * Unifies basic blocks that share content. + */ + +#pragma once + +#include +#include +#include + +namespace dev +{ +namespace eth +{ + +class AssemblyItem; +using AssemblyItems = std::vector; + +/** + * Optimizer class to be used to unify blocks that share content. + * Modifies the passed vector in place. + */ +class BlockDeduplicator +{ +public: + BlockDeduplicator(AssemblyItems& _items): m_items(_items) {} + /// @returns true if something was changed + bool deduplicate(); + +private: + /// Iterator that skips tags skips to the end if (all branches of) the control + /// flow does not continue to the next instruction. + struct BlockIterator: std::iterator + { + public: + BlockIterator(AssemblyItems::const_iterator _it, AssemblyItems::const_iterator _end): + it(_it), end(_end) { } + BlockIterator& operator++(); + bool operator==(BlockIterator const& _other) const { return it == _other.it; } + bool operator!=(BlockIterator const& _other) const { return it != _other.it; } + AssemblyItem const& operator*() const { return *it; } + AssemblyItems::const_iterator it; + AssemblyItems::const_iterator end; + }; + + AssemblyItems& m_items; +}; + +} +} diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index e50469dd6..efc9316b0 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -29,6 +29,7 @@ #include #include #include +#include using namespace std; using namespace dev::eth; @@ -125,7 +126,7 @@ public: BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end()); } - void checkCFG(AssemblyItems const& _input, AssemblyItems const& _expectation) + AssemblyItems getCFG(AssemblyItems const& _input) { AssemblyItems output = _input; // Running it four times should be enough for these tests. @@ -138,6 +139,12 @@ public: back_inserter(optItems)); output = move(optItems); } + return output; + } + + void checkCFG(AssemblyItems const& _input, AssemblyItems const& _expectation) + { + AssemblyItems output = getCFG(_input); BOOST_CHECK_EQUAL_COLLECTIONS(_expectation.begin(), _expectation.end(), output.begin(), output.end()); } @@ -925,6 +932,35 @@ BOOST_AUTO_TEST_CASE(control_flow_graph_do_not_remove_returned_to) checkCFG(input, {u256(2)}); } +BOOST_AUTO_TEST_CASE(block_deduplicator) +{ + AssemblyItems input{ + AssemblyItem(PushTag, 2), + AssemblyItem(PushTag, 1), + AssemblyItem(PushTag, 3), + u256(6), + eth::Instruction::SWAP3, + eth::Instruction::JUMP, + AssemblyItem(Tag, 1), + u256(6), + eth::Instruction::SWAP3, + eth::Instruction::JUMP, + AssemblyItem(Tag, 2), + u256(6), + eth::Instruction::SWAP3, + eth::Instruction::JUMP, + AssemblyItem(Tag, 3) + }; + BlockDeduplicator dedup(input); + dedup.deduplicate(); + + set pushTags; + for (AssemblyItem const& item: input) + if (item.type() == PushTag) + pushTags.insert(item.data()); + BOOST_CHECK_EQUAL(pushTags.size(), 2); +} + BOOST_AUTO_TEST_SUITE_END() } From bf51bfef0e59c3be4e1ddcadc6b0c44a15b5d272 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 12 May 2015 17:00:23 +0200 Subject: [PATCH 038/157] Removed unnecessary include. --- libevmasm/BlockDeduplicator.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libevmasm/BlockDeduplicator.cpp b/libevmasm/BlockDeduplicator.cpp index ca4f7e21a..eadbe1b40 100644 --- a/libevmasm/BlockDeduplicator.cpp +++ b/libevmasm/BlockDeduplicator.cpp @@ -26,8 +26,6 @@ #include #include -#include - using namespace std; using namespace dev; using namespace dev::eth; From 18e223e9456195dbc56528927d211805de57202a Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 12 May 2015 17:50:41 +0200 Subject: [PATCH 039/157] Reverse if and else body. --- libsolidity/Compiler.cpp | 12 ++++-- test/libsolidity/SolidityCompiler.cpp | 59 +++++++++++++-------------- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index bcd4f9d68..66c503172 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -377,12 +377,16 @@ bool Compiler::visit(IfStatement const& _ifStatement) StackHeightChecker checker(m_context); CompilerContext::LocationSetter locationSetter(m_context, _ifStatement); compileExpression(_ifStatement.getCondition()); - eth::AssemblyItem trueTag = m_context.appendConditionalJump(); + m_context << eth::Instruction::ISZERO; + eth::AssemblyItem falseTag = m_context.appendConditionalJump(); + eth::AssemblyItem endTag = falseTag; + _ifStatement.getTrueStatement().accept(*this); if (_ifStatement.getFalseStatement()) + { + endTag = m_context.appendJumpToNew(); + m_context << falseTag; _ifStatement.getFalseStatement()->accept(*this); - eth::AssemblyItem endTag = m_context.appendJumpToNew(); - m_context << trueTag; - _ifStatement.getTrueStatement().accept(*this); + } m_context << endTag; checker.check(); diff --git a/test/libsolidity/SolidityCompiler.cpp b/test/libsolidity/SolidityCompiler.cpp index aa83c4650..dda7847ed 100644 --- a/test/libsolidity/SolidityCompiler.cpp +++ b/test/libsolidity/SolidityCompiler.cpp @@ -116,36 +116,35 @@ BOOST_AUTO_TEST_CASE(ifStatement) bytes code = compileContract(sourceCode); unsigned shift = 60; unsigned boilerplateSize = 73; - bytes expectation({byte(Instruction::JUMPDEST), - byte(Instruction::PUSH1), 0x0, - byte(Instruction::DUP1), - byte(Instruction::PUSH1), byte(0x1b + shift), // "true" target - byte(Instruction::JUMPI), - // new check "else if" condition - byte(Instruction::DUP1), - byte(Instruction::ISZERO), - byte(Instruction::PUSH1), byte(0x13 + shift), - byte(Instruction::JUMPI), - // "else" body - byte(Instruction::PUSH1), 0x4f, - byte(Instruction::POP), - byte(Instruction::PUSH1), byte(0x17 + shift), // exit path of second part - byte(Instruction::JUMP), - // "else if" body - byte(Instruction::JUMPDEST), - byte(Instruction::PUSH1), 0x4e, - byte(Instruction::POP), - byte(Instruction::JUMPDEST), - byte(Instruction::PUSH1), byte(0x1f + shift), - byte(Instruction::JUMP), - // "if" body - byte(Instruction::JUMPDEST), - byte(Instruction::PUSH1), 0x4d, - byte(Instruction::POP), - byte(Instruction::JUMPDEST), - byte(Instruction::JUMPDEST), - byte(Instruction::POP), - byte(Instruction::JUMP)}); + bytes expectation({ + byte(Instruction::JUMPDEST), + byte(Instruction::PUSH1), 0x0, + byte(Instruction::DUP1), + byte(Instruction::ISZERO), + byte(Instruction::PUSH1), byte(0x0f + shift), // "false" target + byte(Instruction::JUMPI), + // "if" body + byte(Instruction::PUSH1), 0x4d, + byte(Instruction::POP), + byte(Instruction::PUSH1), byte(0x21 + shift), + byte(Instruction::JUMP), + // new check "else if" condition + byte(Instruction::JUMPDEST), + byte(Instruction::DUP1), + byte(Instruction::ISZERO), + byte(Instruction::ISZERO), + byte(Instruction::PUSH1), byte(0x1c + shift), + byte(Instruction::JUMPI), + // "else if" body + byte(Instruction::PUSH1), 0x4e, + byte(Instruction::POP), + byte(Instruction::PUSH1), byte(0x20 + shift), + byte(Instruction::JUMP), + // "else" body + byte(Instruction::JUMPDEST), + byte(Instruction::PUSH1), 0x4f, + byte(Instruction::POP), + }); checkCodePresentAt(code, expectation, boilerplateSize); } From 2d2efc070a6239a76e80e2d452f1f4fad4b20985 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 12 May 2015 17:52:03 +0200 Subject: [PATCH 040/157] Gas estimation --- mix/CodeModel.cpp | 49 +++++++++++++++++++++++++++++++++++ mix/CodeModel.h | 25 ++++++++++++++++++ mix/qml/CodeEditorView.qml | 4 +++ mix/qml/WebCodeEditor.qml | 8 ++++++ mix/qml/html/cm/solarized.css | 4 +++ mix/qml/html/codeeditor.js | 23 +++++++++++++++- 6 files changed, 112 insertions(+), 1 deletion(-) diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 636a665e6..ecdb46be3 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include #include "QContractDefinition.h" @@ -41,6 +43,7 @@ #include "CodeHighlighter.h" #include "FileIo.h" #include "CodeModel.h" +#include "QBigInt.h" using namespace dev::mix; @@ -50,6 +53,7 @@ const std::set c_predefinedContracts = namespace { +using namespace dev::eth; using namespace dev::solidity; class CollectLocalsVisitor: public ASTConstVisitor @@ -185,6 +189,7 @@ CodeModel::CodeModel(): qRegisterMetaType("QContractDefinition*"); qRegisterMetaType("QFunctionDefinition*"); qRegisterMetaType("QVariableDeclaration*"); + //qRegisterMetaType("GasMap"); qmlRegisterType("org.ethereum.qml", 1, 0, "QFunctionDefinition"); qmlRegisterType("org.ethereum.qml", 1, 0, "QVariableDeclaration"); } @@ -292,6 +297,7 @@ void CodeModel::runCompilationJob(int _jobId) } } cs.compile(false); + gasEstimation(cs); collectContracts(cs, sourceNames); } catch (dev::Exception const& _exception) @@ -314,6 +320,49 @@ void CodeModel::runCompilationJob(int _jobId) emit stateChanged(); } +void CodeModel::gasEstimation(solidity::CompilerStack const& _cs) +{ + m_gasCostsMaps.clear(); + for (std::string n: _cs.getContractNames()) + { + + ContractDefinition const& contractDefinition = _cs.getContractDefinition(n); + QString sourceName = QString::fromStdString(*contractDefinition.getLocation().sourceName); + + if (!m_gasCostsMaps.contains(sourceName)) + m_gasCostsMaps.insert(sourceName, QVariantList()); + + if (!contractDefinition.isFullyImplemented()) + continue; + dev::solidity::SourceUnit const& sourceUnit = _cs.getAST(*contractDefinition.getLocation().sourceName); + AssemblyItems const* items = _cs.getRuntimeAssemblyItems(n); + + StructuralGasEstimator estimator; + std::map gasCosts = estimator.breakToStatementLevel(estimator.performEstimation(*items, std::vector({&sourceUnit})), {&sourceUnit}); + + for (auto gasIte = gasCosts.begin(); gasIte != gasCosts.end(); ++gasIte) + { + SourceLocation location = gasIte->first->getLocation(); + GasMeter::GasConsumption cost = gasIte->second; + GasMap* gas = new GasMap(location.start, location.end, (new QBigInt(cost.value))->value()); + m_gasCostsMaps.find(sourceName).value().push_back(QVariant::fromValue(gas)); + } + } +} + +QVariantList CodeModel::gasCostByDocumentId(QString const& _documentId) const +{ + if (m_gasCostsMaps.contains(_documentId)) + { + auto sourceMapIter = m_gasCostsMaps.find(_documentId); + int gg = sourceMapIter.value().size(); + Q_UNUSED(gg); + return sourceMapIter.value(); + } + else + return QVariantList(); +} + void CodeModel::collectContracts(dev::solidity::CompilerStack const& _cs, std::vector const& _sourceNames) { Guard pl(x_pendingContracts); diff --git a/mix/CodeModel.h b/mix/CodeModel.h index 3f713a17b..a1a2c29ec 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -32,6 +32,7 @@ #include #include #include "SolidityType.h" +#include "QBigInt.h" class QTextDocument; @@ -126,7 +127,24 @@ struct SourceMap LocationMap functions; }; +class GasMap: public QObject +{ + Q_OBJECT + + Q_PROPERTY(int start MEMBER m_start CONSTANT) + Q_PROPERTY(int end MEMBER m_end CONSTANT) + Q_PROPERTY(QString gas MEMBER m_gas CONSTANT) + +public: + GasMap(int _start, int _end, QString _gas): m_start(_start), m_end(_end), m_gas(_gas) {} + + int m_start; + int m_end; + QString m_gas; +}; + using SourceMaps = QMap; //by source id +using GasCostsMaps = QMap*/>; //gas cost by contract name /// Code compilation model. Compiles contracts in background an provides compiled contract data class CodeModel: public QObject @@ -166,6 +184,10 @@ public: bool isContractOrFunctionLocation(dev::SourceLocation const& _location); /// Get funciton name by location QString resolveFunctionName(dev::SourceLocation const& _location); + /// Gas estimation for compiled sources + void gasEstimation(solidity::CompilerStack const& _cs); + /// Gas cost by doc id + Q_INVOKABLE QVariantList gasCostByDocumentId(QString const& _documentId) const; signals: /// Emited on compilation state change @@ -201,6 +223,7 @@ private: mutable dev::Mutex x_contractMap; ContractMap m_contractMap; SourceMaps m_sourceMaps; + GasCostsMaps m_gasCostsMaps; std::unique_ptr m_codeHighlighterSettings; QThread m_backgroundThread; BackgroundWorker m_backgroundWorker; @@ -214,3 +237,5 @@ private: } } + +//Q_DECLARE_METATYPE(dev::mix::GasMap) diff --git a/mix/qml/CodeEditorView.qml b/mix/qml/CodeEditorView.qml index e4d62ed81..08bb072f5 100644 --- a/mix/qml/CodeEditorView.qml +++ b/mix/qml/CodeEditorView.qml @@ -177,6 +177,10 @@ Item { } onCompilationComplete: { sourceInError = ""; + var gasCosts = codeModel.gasCostByDocumentId(currentDocumentId); + var editor = getEditor(currentDocumentId); + if (editor) + editor.displayGasCosts(gasCosts); } } diff --git a/mix/qml/WebCodeEditor.qml b/mix/qml/WebCodeEditor.qml index 38f2327b1..a2602304a 100644 --- a/mix/qml/WebCodeEditor.qml +++ b/mix/qml/WebCodeEditor.qml @@ -83,6 +83,14 @@ Item { editorBrowser.runJavaScript("setFontSize(" + size + ")", function(result) {}); } + function displayGasCosts(gasCosts) { + + //console.log(gasCosts); + //console.log(JSON.stringify(gasCosts)); + if (initialized && editorBrowser) + editorBrowser.runJavaScript("displayGasCosts('" + JSON.stringify(gasCosts) + "')", function(result) {}); + } + Clipboard { id: clipboard diff --git a/mix/qml/html/cm/solarized.css b/mix/qml/html/cm/solarized.css index b8cede806..046042450 100644 --- a/mix/qml/html/cm/solarized.css +++ b/mix/qml/html/cm/solarized.css @@ -189,3 +189,7 @@ view-port } span.CodeMirror-selectedtext { color: #586e75 !important; } + +.gasCost { + background: #b58900 !important; +} diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index d25fbd091..cc5e9a28c 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -3,7 +3,7 @@ var editor = CodeMirror(document.body, { //styleActiveLine: true, matchBrackets: true, autofocus: true, - gutters: ["CodeMirror-linenumbers", "breakpoints"], + gutters: ["CodeMirror-linenumbers", "breakpoints", "gasCost"], autoCloseBrackets: true, styleSelectedText: true }); @@ -203,5 +203,26 @@ setFontSize = function(size) editor.refresh(); } +makeGasCostMarker = function(value) { + var marker = document.createElement("div"); + marker.style.color = "#822"; + marker.innerHTML = value; + return marker; +}; + +displayGasCosts = function(gasCosts) +{ + gasCosts = JSON.parse(gasCosts); + for (var i in gasCosts) + { + var line = editor.posFromIndex(gasCosts[i].start); + console.log("___________") + console.log(line.line); + console.log(gasCosts[i].start); + //editor.setGutterMarker(line.line, "gasCost", makeGasCostMarker(gasCosts[i].gas)); + editor.markText(editor.posFromIndex(gasCosts[i].start), editor.posFromIndex(gasCosts[i].end), { className: "gasCost" }); + } +} + editor.setOption("extraKeys", extraKeys); From 368532c107f383c909dde8e951693c9f42f00b0d Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 13 May 2015 00:26:43 +0300 Subject: [PATCH 041/157] Extra diagnostics, assertions and fail-safes for tracking BadRoot bug. --- libdevcrypto/MemoryDB.cpp | 34 +++++++++++++++++------ libdevcrypto/MemoryDB.h | 11 ++++++-- libdevcrypto/OverlayDB.cpp | 57 +++++++++++++++++++++++++------------- libdevcrypto/OverlayDB.h | 8 +++--- libdevcrypto/TrieDB.cpp | 2 +- libdevcrypto/TrieDB.h | 36 ++++++++++++++---------- libethereum/BlockChain.cpp | 9 +++++- libethereum/Client.cpp | 2 +- libethereum/State.cpp | 12 +++++++- test/libdevcrypto/trie.cpp | 10 +++++++ 10 files changed, 128 insertions(+), 53 deletions(-) diff --git a/libdevcrypto/MemoryDB.cpp b/libdevcrypto/MemoryDB.cpp index 4b08db083..2cf56475b 100644 --- a/libdevcrypto/MemoryDB.cpp +++ b/libdevcrypto/MemoryDB.cpp @@ -32,6 +32,7 @@ const char* DBWarn::name() { return "TDB"; } std::unordered_map MemoryDB::get() const { + ReadGuard l(x_this); std::unordered_map ret; for (auto const& i: m_main) if (!m_enforceRefs || i.second.second > 0) @@ -39,21 +40,34 @@ std::unordered_map MemoryDB::get() const return ret; } +MemoryDB& MemoryDB::operator=(MemoryDB const& _c) +{ + if (this == &_c) + return *this; + ReadGuard l(_c.x_this); + WriteGuard l2(x_this); + m_main = _c.m_main; + m_aux = _c.m_aux; + return *this; +} + std::string MemoryDB::lookup(h256 const& _h) const { + ReadGuard l(x_this); auto it = m_main.find(_h); if (it != m_main.end()) { if (!m_enforceRefs || it->second.second > 0) return it->second.first; -// else if (m_enforceRefs && m_refCount.count(it->first) && !m_refCount.at(it->first)) -// cnote << "Lookup required for value with no refs. Let's hope it's in the DB." << _h; + else + cwarn << "Lookup required for value with refcount == 0. This is probably a critical trie issue" << _h; } return std::string(); } bool MemoryDB::exists(h256 const& _h) const { + ReadGuard l(x_this); auto it = m_main.find(_h); if (it != m_main.end() && (!m_enforceRefs || it->second.second > 0)) return true; @@ -62,6 +76,7 @@ bool MemoryDB::exists(h256 const& _h) const void MemoryDB::insert(h256 const& _h, bytesConstRef _v) { + WriteGuard l(x_this); auto it = m_main.find(_h); if (it != m_main.end()) { @@ -77,34 +92,34 @@ void MemoryDB::insert(h256 const& _h, bytesConstRef _v) bool MemoryDB::kill(h256 const& _h) { + ReadGuard l(x_this); if (m_main.count(_h)) { if (m_main[_h].second > 0) + { m_main[_h].second--; + return true; + } #if ETH_PARANOIA else { // If we get to this point, then there was probably a node in the level DB which we need to remove and which we have previously // used as part of the memory-based MemoryDB. Nothing to be worried about *as long as the node exists in the DB*. dbdebug << "NOKILL-WAS" << _h; - return false; } dbdebug << "KILL" << _h << "=>" << m_main[_h].second; - return true; } else { dbdebug << "NOKILL" << _h; - return false; - } -#else - } - return true; #endif + } + return false; } void MemoryDB::purge() { + WriteGuard l(x_this); for (auto it = m_main.begin(); it != m_main.end(); ) if (it->second.second) ++it; @@ -114,6 +129,7 @@ void MemoryDB::purge() h256Hash MemoryDB::keys() const { + ReadGuard l(x_this); h256Hash ret; for (auto const& i: m_main) if (i.second.second) diff --git a/libdevcrypto/MemoryDB.h b/libdevcrypto/MemoryDB.h index 3169d8fbc..169682815 100644 --- a/libdevcrypto/MemoryDB.h +++ b/libdevcrypto/MemoryDB.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -43,6 +44,9 @@ class MemoryDB public: MemoryDB() {} + MemoryDB(MemoryDB const& _c) { operator=(_c); } + + MemoryDB& operator=(MemoryDB const& _c); void clear() { m_main.clear(); } // WARNING !!!! didn't originally clear m_refCount!!! std::unordered_map get() const; @@ -53,13 +57,14 @@ public: bool kill(h256 const& _h); void purge(); - bytes lookupAux(h256 const& _h) const { try { return m_aux.at(_h).first; } catch (...) { return bytes(); } } - 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); } + bytes lookupAux(h256 const& _h) const { ReadGuard l(x_this); auto it = m_aux.find(_h); if (it != m_aux.end() && (!m_enforceRefs || it->second.second)) return it->second.first; return bytes(); } + void removeAux(h256 const& _h) { WriteGuard l(x_this); m_aux[_h].second = false; } + void insertAux(h256 const& _h, bytesConstRef _v) { WriteGuard l(x_this); m_aux[_h] = make_pair(_v.toBytes(), true); } h256Hash keys() const; protected: + mutable SharedMutex x_this; std::unordered_map> m_main; std::unordered_map> m_aux; diff --git a/libdevcrypto/OverlayDB.cpp b/libdevcrypto/OverlayDB.cpp index 87c8a0927..957c7f0e3 100644 --- a/libdevcrypto/OverlayDB.cpp +++ b/libdevcrypto/OverlayDB.cpp @@ -19,6 +19,7 @@ * @date 2014 */ +#include #include #include #include @@ -29,6 +30,8 @@ using namespace dev; namespace dev { +h256 const EmptyTrie = sha3(rlp("")); + OverlayDB::~OverlayDB() { if (m_db.use_count() == 1 && m_db.get()) @@ -41,30 +44,41 @@ void OverlayDB::commit() { ldb::WriteBatch batch; // cnote << "Committing nodes to disk DB:"; - for (auto const& i: m_main) + DEV_READ_GUARDED(x_this) { -// cnote << i.first << "#" << m_main[i.first].second; - if (i.second.second) - batch.Put(ldb::Slice((char const*)i.first.data(), i.first.size), ldb::Slice(i.second.first.data(), i.second.first.size())); - } - for (auto const& i: m_aux) - if (i.second.second) + for (auto const& i: m_main) { - bytes b = i.first.asBytes(); - b.push_back(255); // for aux - batch.Put(bytesConstRef(&b), bytesConstRef(&i.second.first)); + if (i.second.second) + batch.Put(ldb::Slice((char const*)i.first.data(), i.first.size), ldb::Slice(i.second.first.data(), i.second.first.size())); +// cnote << i.first << "#" << m_main[i.first].second; } - m_db->Write(m_writeOptions, &batch); + for (auto const& i: m_aux) + if (i.second.second) + { + bytes b = i.first.asBytes(); + b.push_back(255); // for aux + batch.Put(bytesConstRef(&b), bytesConstRef(&i.second.first)); + } + } + + while (true) + { + ldb::Status o = m_db->Write(m_writeOptions, &batch); + if (o.ok()) + break; + cwarn << "Error writing to database. Sleeping a while then retrying. If it keeps saying this, free up some space!"; + this_thread::sleep_for(chrono::milliseconds(500)); + } m_aux.clear(); m_main.clear(); } } -bytes OverlayDB::lookupAux(h256 _h) const +bytes OverlayDB::lookupAux(h256 const& _h) const { bytes ret = MemoryDB::lookupAux(_h); if (!ret.empty()) - return ret; + return move(ret); std::string v; bytes b = _h.asBytes(); b.push_back(255); // for aux @@ -76,18 +90,19 @@ bytes OverlayDB::lookupAux(h256 _h) const void OverlayDB::rollback() { + WriteGuard l(x_this); m_main.clear(); } -std::string OverlayDB::lookup(h256 _h) const +std::string OverlayDB::lookup(h256 const& _h) const { std::string ret = MemoryDB::lookup(_h); if (ret.empty() && m_db) m_db->Get(m_readOptions, ldb::Slice((char const*)_h.data(), 32), &ret); - return ret; + return move(ret); } -bool OverlayDB::exists(h256 _h) const +bool OverlayDB::exists(h256 const& _h) const { if (MemoryDB::exists(_h)) return true; @@ -97,16 +112,20 @@ bool OverlayDB::exists(h256 _h) const return !ret.empty(); } -void OverlayDB::kill(h256 _h) +void OverlayDB::kill(h256 const& _h) { -#if ETH_PARANOIA +#if ETH_PARANOIA || 1 if (!MemoryDB::kill(_h)) { std::string ret; if (m_db) m_db->Get(m_readOptions, ldb::Slice((char const*)_h.data(), 32), &ret); - if (ret.empty()) + // No point node ref decreasing for EmptyTrie since we never bother incrementing it in the first place for + // empty storage tries. + if (ret.empty() && _h != EmptyTrie) cnote << "Decreasing DB node ref count below zero with no DB node. Probably have a corrupt Trie." << _h; + + // TODO: for 1.1: ref-counted triedb. } #else MemoryDB::kill(_h); diff --git a/libdevcrypto/OverlayDB.h b/libdevcrypto/OverlayDB.h index 7f7736ac1..2e5428bdf 100644 --- a/libdevcrypto/OverlayDB.h +++ b/libdevcrypto/OverlayDB.h @@ -46,11 +46,11 @@ public: void commit(); void rollback(); - std::string lookup(h256 _h) const; - bool exists(h256 _h) const; - void kill(h256 _h); + std::string lookup(h256 const& _h) const; + bool exists(h256 const& _h) const; + void kill(h256 const& _h); - bytes lookupAux(h256 _h) const; + bytes lookupAux(h256 const& _h) const; private: using MemoryDB::clear; diff --git a/libdevcrypto/TrieDB.cpp b/libdevcrypto/TrieDB.cpp index 6f84a3e29..719bd74ad 100644 --- a/libdevcrypto/TrieDB.cpp +++ b/libdevcrypto/TrieDB.cpp @@ -25,6 +25,6 @@ using namespace std; using namespace dev; h256 const dev::c_shaNull = sha3(rlp("")); -h256 const dev::EmptyTrie = c_shaNull; +h256 const dev::EmptyTrie = sha3(rlp("")); const char* TrieDBChannel::name() { return "-T-"; } diff --git a/libdevcrypto/TrieDB.h b/libdevcrypto/TrieDB.h index ff2bcc589..29b412bab 100644 --- a/libdevcrypto/TrieDB.h +++ b/libdevcrypto/TrieDB.h @@ -79,7 +79,7 @@ public: void open(DB* _db) { m_db = _db; } void open(DB* _db, h256 const& _root, Verification _v = Verification::Normal) { m_db = _db; setRoot(_root, _v); } - void init() { setRoot(insertNode(&RLPNull)); assert(node(m_root).size()); } + void init() { setRoot(forceInsertNode(&RLPNull)); assert(node(m_root).size()); } void setRoot(h256 const& _root, Verification _v = Verification::Normal) { @@ -88,11 +88,13 @@ public: { if (m_root == c_shaNull && !m_db->exists(m_root)) init(); - - /*std::cout << "Setting root to " << _root << " (patched to " << m_root << ")" << std::endl;*/ + } + /*std::cout << "Setting root to " << _root << " (patched to " << m_root << ")" << std::endl;*/ +#if ETH_DEBUG + if (_v == Verification::Normal) +#endif if (!node(m_root).size()) BOOST_THROW_EXCEPTION(RootNotFound()); - } } /// True if the trie is uninitialised (i.e. that the DB doesn't contain the root node). @@ -282,11 +284,17 @@ private: std::string deref(RLP const& _n) const; std::string node(h256 _h) const { return m_db->lookup(_h); } - void insertNode(h256 _h, bytesConstRef _v) { m_db->insert(_h, _v); } - void killNode(h256 _h) { m_db->kill(_h); } - h256 insertNode(bytesConstRef _v) { auto h = sha3(_v); insertNode(h, _v); return h; } - void killNode(RLP const& _d) { if (_d.data().size() >= 32) killNode(sha3(_d.data())); } + // These are low-level node insertion functions that just go straight through into the DB. + h256 forceInsertNode(bytesConstRef _v) { auto h = sha3(_v); forceInsertNode(h, _v); return h; } + void forceInsertNode(h256 _h, bytesConstRef _v) { m_db->insert(_h, _v); } + void forceKillNode(h256 _h) { m_db->kill(_h); } + + // This are semantically-aware node insertion functions that only kills when the node's + // data is < 32 bytes. It can safely be used when pruning the trie but won't work correctly + // for the special case of the root (which is always looked up via a hash). In that case, + // use forceKillNode(). + void killNode(RLP const& _d) { if (_d.data().size() >= 32) forceKillNode(sha3(_d.data())); } h256 m_root; DB* m_db = nullptr; @@ -743,8 +751,8 @@ template void GenericTrieDB::insert(bytesConstRef _key, bytesCons // However, we know it's the root node and thus always hashed. // So, if it's less than 32 (and thus should have been deleted but wasn't) then we delete it here. if (rv.size() < 32) - killNode(m_root); - m_root = insertNode(&b); + forceKillNode(m_root); + m_root = forceInsertNode(&b); } template std::string GenericTrieDB::at(bytesConstRef _key) const @@ -890,8 +898,8 @@ template void GenericTrieDB::remove(bytesConstRef _key) if (b.size()) { if (rv.size() < 32) - killNode(m_root); - m_root = insertNode(&b); + forceKillNode(m_root); + m_root = forceInsertNode(&b); } } @@ -1081,7 +1089,7 @@ template RLPStream& GenericTrieDB::streamNode(RLPStream& _s, byte if (_b.size() < 32) _s.appendRaw(_b); else - _s.append(insertNode(&_b)); + _s.append(forceInsertNode(&_b)); return _s; } @@ -1122,7 +1130,7 @@ template bytes GenericTrieDB::graft(RLP const& _orig) // remove second item from the trie after derefrencing it into s & n. auto lh = _orig[1].toHash(); s = node(lh); - killNode(lh); + forceKillNode(lh); n = RLP(s); } assert(n.itemCount() == 2); diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index f13f83588..32a11ee53 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -466,7 +466,14 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import blb.blooms.push_back(s.receipt(i).bloom()); br.receipts.push_back(s.receipt(i)); } - s.cleanup(true); + try { + s.cleanup(true); + } + catch (BadRoot) + { + cwarn << "BadRoot error. Retrying import later."; + BOOST_THROW_EXCEPTION(FutureTime()); + } td = pd.totalDifficulty + tdIncrease; diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index a43c98aa2..6d934f3ad 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -164,7 +164,7 @@ const char* ClientDetail::name() { return EthTeal "⧫" EthCoal " ●"; } #endif Client::Client(p2p::Host* _extNet, std::string const& _dbPath, WithExisting _forceAction, u256 _networkId): - Worker("eth"), + Worker("eth", 0), m_vc(_dbPath), m_bc(_dbPath, max(m_vc.action(), _forceAction), [](unsigned d, unsigned t){ cerr << "REVISING BLOCKCHAIN: Processed " << d << " of " << t << "...\r"; }), m_gp(new TrivialGasPricer), diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 584de461b..167d6236e 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -707,11 +707,21 @@ void State::cleanup(bool _fullCommit) { if (_fullCommit) { - paranoia("immediately before database commit", true); // Commit the new trie to disk. clog(StateTrace) << "Committing to disk: stateRoot" << m_currentBlock.stateRoot << "=" << rootHash() << "=" << toHex(asBytes(m_db.lookup(rootHash()))); + + try { + EnforceRefs er(m_db, true); + rootHash(); + } + catch (BadRoot const&) + { + clog(StateChat) << "Trie corrupt! :-("; + throw; + } + m_db.commit(); clog(StateTrace) << "Committed: stateRoot" << m_currentBlock.stateRoot << "=" << rootHash() << "=" << toHex(asBytes(m_db.lookup(rootHash()))); diff --git a/test/libdevcrypto/trie.cpp b/test/libdevcrypto/trie.cpp index 3b3fa1dd2..d41739a01 100644 --- a/test/libdevcrypto/trie.cpp +++ b/test/libdevcrypto/trie.cpp @@ -102,10 +102,13 @@ BOOST_AUTO_TEST_CASE(hex_encoded_securetrie_test) { next_permutation(ss.begin(), ss.end()); MemoryDB m; + EnforceRefs r(m, true); GenericTrieDB t(&m); MemoryDB hm; + EnforceRefs hr(hm, true); HashedGenericTrieDB ht(&hm); MemoryDB fm; + EnforceRefs fr(fm, true); FatGenericTrieDB ft(&fm); t.init(); ht.init(); @@ -164,10 +167,13 @@ BOOST_AUTO_TEST_CASE(trie_test_anyorder) { next_permutation(ss.begin(), ss.end()); MemoryDB m; + EnforceRefs r(m, true); GenericTrieDB t(&m); MemoryDB hm; + EnforceRefs hr(hm, true); HashedGenericTrieDB ht(&hm); MemoryDB fm; + EnforceRefs fr(fm, true); FatGenericTrieDB ft(&fm); t.init(); ht.init(); @@ -244,10 +250,13 @@ BOOST_AUTO_TEST_CASE(trie_tests_ordered) } MemoryDB m; + EnforceRefs r(m, true); GenericTrieDB t(&m); MemoryDB hm; + EnforceRefs hr(hm, true); HashedGenericTrieDB ht(&hm); MemoryDB fm; + EnforceRefs fr(fm, true); FatGenericTrieDB ft(&fm); t.init(); ht.init(); @@ -360,6 +369,7 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) #endif { MemoryDB m; + EnforceRefs r(m, true); GenericTrieDB d(&m); d.init(); // initialise as empty tree. MemTrie t; From 6978731367a1fe1caec11abaaaeea92349125c8a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 13 May 2015 00:36:13 +0300 Subject: [PATCH 042/157] Bump. --- libdevcore/Common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 06950cbee..6723ab76d 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -28,7 +28,7 @@ using namespace dev; namespace dev { -char const* Version = "0.9.18"; +char const* Version = "0.9.19"; const u256 UndefinedU256 = ~(u256)0; From 44cd78d647c0d6162ceda1bd2724983047d46b9c Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 13 May 2015 10:14:34 +0200 Subject: [PATCH 043/157] Improve getpass() usage As can be seen from: http://unixhelp.ed.ac.uk/CGI/man-cgi?getpass+3 getpass() is a deprecated function and it's advised not to use it. What's more all signals are disabled so (SIGINT, SIGQUIT, SIGSTOP, SIGTSTOP) will do nothing and as such if the user wants to quit the program while typing the password in the password loop he is out of luck. With this commit we get a manual version of getpass(), inspired by this SO answer: http://stackoverflow.com/a/1196696/110395 --- libdevcore/CommonIO.cpp | 28 +++++++++++++++++++++++++++- libdevcore/Exceptions.h | 1 + 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/libdevcore/CommonIO.cpp b/libdevcore/CommonIO.cpp index 80ad7ecf9..10c53ddb9 100644 --- a/libdevcore/CommonIO.cpp +++ b/libdevcore/CommonIO.cpp @@ -24,6 +24,9 @@ #include #include #include "Exceptions.h" +#ifndef _WIN32 +#include +#endif using namespace std; using namespace dev; @@ -126,6 +129,29 @@ std::string dev::getPassword(std::string const& _prompt) std::getline(cin, ret); return ret; #else - return getpass(_prompt.c_str()); + struct termios oflags; + struct termios nflags; + char password[128]; + + // disable echo in the terminal + tcgetattr(fileno(stdin), &oflags); + nflags = oflags; + nflags.c_lflag &= ~ECHO; + nflags.c_lflag |= ECHONL; + + if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) + BOOST_THROW_EXCEPTION(ExternalFunctionFailure("tcsetattr")); + + printf("%s", _prompt.c_str()); + if (!fgets(password, sizeof(password), stdin)) + BOOST_THROW_EXCEPTION(ExternalFunctionFailure("fgets")); + password[strlen(password) - 1] = 0; + + // restore terminal + if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { + BOOST_THROW_EXCEPTION(ExternalFunctionFailure("tcsetattr")); + } + + return password; #endif } diff --git a/libdevcore/Exceptions.h b/libdevcore/Exceptions.h index 36c624a71..025568efa 100644 --- a/libdevcore/Exceptions.h +++ b/libdevcore/Exceptions.h @@ -54,6 +54,7 @@ struct FileError: virtual Exception {}; struct Overflow: virtual Exception {}; struct InterfaceNotSupported: virtual Exception { public: InterfaceNotSupported(std::string _f): Exception("Interface " + _f + " not supported.") {} }; struct FailedInvariant: virtual Exception {}; +struct ExternalFunctionFailure: virtual Exception { public: ExternalFunctionFailure(std::string _f): Exception("Function " + _f + "() failed.") {} }; // error information to be added to exceptions using errinfo_invalidSymbol = boost::error_info; From 6439506e376c3876ef15ff779b7772b362a4011d Mon Sep 17 00:00:00 2001 From: subtly Date: Wed, 13 May 2015 10:32:22 +0200 Subject: [PATCH 044/157] Fix for when macos doesn't set HOME environment variable. --- libdevcrypto/FileSystem.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libdevcrypto/FileSystem.cpp b/libdevcrypto/FileSystem.cpp index ed054553d..e3b8c6e3f 100644 --- a/libdevcrypto/FileSystem.cpp +++ b/libdevcrypto/FileSystem.cpp @@ -25,8 +25,13 @@ #include #include -#ifdef _WIN32 +#if defined(_WIN32) #include +#elif defined(__APPLE__) +#include +#include +#include +#include #endif #include using namespace std; @@ -51,6 +56,15 @@ std::string dev::getDataDir(std::string _prefix) #else boost::filesystem::path dataDirPath; char const* homeDir = getenv("HOME"); +#if defined(__APPLE__) + if (!homeDir || strlen(homeDir) == 0) + { + struct passwd* pwd = getpwuid(getuid()); + if (pwd) + homeDir = pwd->pw_dir; + } +#endif + if (!homeDir || strlen(homeDir) == 0) dataDirPath = boost::filesystem::path("/"); else From 1aabac3cfcf8cfdfbfa86c60f8e707feb41c5a06 Mon Sep 17 00:00:00 2001 From: subtly Date: Wed, 13 May 2015 10:37:43 +0200 Subject: [PATCH 045/157] Increase frequency of node discovery by factor of 8 (random lookup every 7 seconds). --- libp2p/NodeTable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libp2p/NodeTable.h b/libp2p/NodeTable.h index 2e10dd891..de139b683 100644 --- a/libp2p/NodeTable.h +++ b/libp2p/NodeTable.h @@ -186,7 +186,7 @@ private: /* todo: replace boost::posix_time; change constants to upper camelcase */ boost::posix_time::milliseconds const c_evictionCheckInterval = boost::posix_time::milliseconds(75); ///< Interval at which eviction timeouts are checked. std::chrono::milliseconds const c_reqTimeout = std::chrono::milliseconds(300); ///< How long to wait for requests (evict, find iterations). - std::chrono::milliseconds const c_bucketRefresh = std::chrono::milliseconds(57600); ///< Refresh interval prevents bucket from becoming stale. [Kademlia] + std::chrono::milliseconds const c_bucketRefresh = std::chrono::milliseconds(7200); ///< Refresh interval prevents bucket from becoming stale. [Kademlia] struct NodeBucket { From 13898c57e7a708ceb27294162b3b12127ae39558 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Wed, 13 May 2015 10:38:23 +0200 Subject: [PATCH 046/157] style --- .../stPreCompiledContractsFiller.json | 1224 ++++++++--------- 1 file changed, 612 insertions(+), 612 deletions(-) diff --git a/test/libethereum/StateTestsFiller/stPreCompiledContractsFiller.json b/test/libethereum/StateTestsFiller/stPreCompiledContractsFiller.json index 41f5bc345..87e6df3cf 100644 --- a/test/libethereum/StateTestsFiller/stPreCompiledContractsFiller.json +++ b/test/libethereum/StateTestsFiller/stPreCompiledContractsFiller.json @@ -1,14 +1,14 @@ { "CallEcrecover0": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", @@ -16,14 +16,14 @@ "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 300000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 300000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -40,18 +40,18 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallEcrecover0_overlappingInputOutput": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", @@ -59,14 +59,14 @@ "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 300000 1 0 0 128 64 32) [[ 0 ]] (MOD (MLOAD 64) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 300000 1 0 0 128 64 32) [[ 0 ]] (MOD (MLOAD 64) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -83,33 +83,33 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallEcrecover0_completeReturnValue": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 3000 1 0 0 128 128 32) [[ 0 ]] (MLOAD 128) }", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 3000 1 0 0 128 128 32) [[ 0 ]] (MLOAD 128) }", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -126,18 +126,18 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallEcrecover0_gas3000": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", @@ -145,14 +145,14 @@ "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 3000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 3000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -169,30 +169,30 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallEcrecover0_BonusGas": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 0 1 1 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 0 1 1 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -209,30 +209,30 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallEcrecover0_Gas2999": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 2999 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 2999 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -249,31 +249,31 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallEcrecover0_0input": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code": "{ [[ 2 ]] (CALL 300000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) }", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code": "{ [[ 2 ]] (CALL 300000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) }", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -290,31 +290,31 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallEcrecover1": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 1) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 100000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 1) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 100000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -331,31 +331,31 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallEcrecover2": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 33 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 65 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 100000 1 0 0 97 97 32) [[ 0 ]] (MOD (MLOAD 97) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 33 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 65 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 100000 1 0 0 97 97 32) [[ 0 ]] (MOD (MLOAD 97) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -372,32 +372,32 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallEcrecover3": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xe4319f4b631c6d0fcfc84045dbcb676865fe5e13", "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code": "{ (MSTORE 0 0x2f380a2dea7e778d81affc2443403b8fe4644db442ae4862ff5bb3732829cdb9) (MSTORE 32 27) (MSTORE 64 0x6b65ccb0558806e9b097f27a396d08f964e37b8b7af6ceeb516ff86739fbea0a) (MSTORE 96 0x37cbc8d883e129a4b1ef9d5f1df53c4f21a3ef147cf2a50a4ede0eb06ce092d4) [[ 2 ]] (CALL 100000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code": "{ (MSTORE 0 0x2f380a2dea7e778d81affc2443403b8fe4644db442ae4862ff5bb3732829cdb9) (MSTORE 32 27) (MSTORE 64 0x6b65ccb0558806e9b097f27a396d08f964e37b8b7af6ceeb516ff86739fbea0a) (MSTORE 96 0x37cbc8d883e129a4b1ef9d5f1df53c4f21a3ef147cf2a50a4ede0eb06ce092d4) [[ 2 ]] (CALL 100000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0)) }", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -414,31 +414,31 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallSha256_0": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "0x600160005260206000602060006000600260fff1600051600055", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "0x600160005260206000602060006000600260fff1600051600055", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -455,32 +455,32 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallSha256_1": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ [[ 2 ]] (CALL 500 2 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ [[ 2 ]] (CALL 500 2 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -497,18 +497,18 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallSha256_1_nonzeroValue": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "100000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "100000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "0000000000000000000000000000000000000002" : { "balance" : "19" }, @@ -518,14 +518,14 @@ "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "200000000", - "nonce" : "0", - "code" : "{ [[ 2 ]] (CALL 200000 2 0x13 0 0 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "200000000", + "nonce" : "0", + "code" : "{ [[ 2 ]] (CALL 200000 2 0x13 0 0 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -542,32 +542,32 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallSha256_2": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xcb39b3bde22925b2f931111130c774761d8895e0e08437c9b396c1e97d10f34d", "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 5 0xf34578907f) [[ 2 ]] (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 5 0xf34578907f) [[ 2 ]] (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -584,32 +584,32 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallSha256_3": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0x7392925565d67be8e9620aacbcfaecd8cb6ec58d709d25da9eccf1d08a41ce35", "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -626,32 +626,32 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallSha256_4": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xaf9613760f72635fbdb44a5a0a63c39f12af30f950a6ee5c971be188e89c4051", "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 100 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 100 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -668,32 +668,32 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallSha256_4_gas99": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xaf9613760f72635fbdb44a5a0a63c39f12af30f950a6ee5c971be188e89c4051", "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 99 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 99 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -710,31 +710,31 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallSha256_5": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 600 2 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 600 2 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -751,31 +751,31 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallRipemd160_0": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "0x600160005260206000602060006000600360fff1600051600055", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "0x600160005260206000602060006000600360fff1600051600055", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -792,32 +792,32 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallRipemd160_1": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0x9c1185a5c5e9fc54612808977ee8f548b2258d31", "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ [[ 2 ]] (CALL 600 3 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ [[ 2 ]] (CALL 600 3 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -834,30 +834,30 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallRipemd160_2": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 5 0xf34578907f) [[ 2 ]] (CALL 600 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 5 0xf34578907f) [[ 2 ]] (CALL 600 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -874,31 +874,31 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallRipemd160_3": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xf34578907f" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 600 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 600 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -915,31 +915,31 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallRipemd160_4": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 120 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 120 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -956,31 +956,31 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallRipemd160_4_gas99": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 119 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 119 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -997,31 +997,31 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallRipemd160_5": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 600 3 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 600 3 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -1038,31 +1038,31 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallIdentitiy_0": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0000000000000000000000000000000000000000000000000000000000000001" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "0x600160005260206000602060006000600460fff1600051600055", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "0x600160005260206000602060006000600460fff1600051600055", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -1079,32 +1079,32 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallIdentitiy_1": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0x00", "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ [[ 2 ]] (CALL 500 4 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ [[ 2 ]] (CALL 500 4 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -1121,18 +1121,18 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallIdentity_1_nonzeroValue": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "100000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "100000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "0000000000000000000000000000000000000004" : { "balance" : "19" }, @@ -1142,14 +1142,14 @@ "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "200000000", - "nonce" : "0", - "code" : "{ [[ 2 ]] (CALL 200000 4 0x13 0 0 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "200000000", + "nonce" : "0", + "code" : "{ [[ 2 ]] (CALL 200000 4 0x13 0 0 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -1166,32 +1166,32 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallIdentity_2": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0x000000000000000000000000000000000000000000000000000000f34578907f", "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 4 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 4 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -1208,32 +1208,32 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallIdentity_3": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0x000000000000000000000000000000000000000000000000000000f34578907f", "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 4 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 4 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -1250,32 +1250,32 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallIdentity_4": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 100 4 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 100 4 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -1292,32 +1292,32 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallIdentity_4_gas18": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x02" : "0x01" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 18 4 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 18 4 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -1334,32 +1334,32 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallIdentity_4_gas17": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x02" : "0x00" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 17 4 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 17 4 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -1376,31 +1376,31 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - }, + }, "CallIdentity_5": { - "env" : { - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", - "currentNumber" : "0", - "currentGasLimit" : "10000000", - "currentDifficulty" : "256", - "currentTimestamp" : 1, - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" - }, - "expect" : { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "10000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "storage" : { "0x" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" } } - }, - "pre" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20000000", - "nonce" : "0", - "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 600 4 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", - "storage": {} - }, + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "20000000", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 600 4 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", + "storage": {} + }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", "nonce" : "0", @@ -1417,6 +1417,6 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "" } - } + } } From d638df83ae76519c506839ea827482074be11fb0 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 13 May 2015 11:45:18 +0300 Subject: [PATCH 047/157] Revert "CMake: set default RUNTIME_OUTPUT_DIRECTORY property to "bin"" --- CMakeLists.txt | 1 - cmake/EthExecutableHelper.cmake | 44 ++++++++++++++++++--------------- cmake/scripts/copydlls.cmake | 3 ++- libevmasm/CMakeLists.txt | 7 +++++- test/CMakeLists.txt | 9 ++----- 5 files changed, 34 insertions(+), 30 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ac37454d8..289cecad8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -295,7 +295,6 @@ message("-- EVMJIT Build LLVM-based JIT EVM (experimental!) ${EVMJIT}" message("------------------------------------------------------------------------") message("") -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") set(CMAKE_THREAD_LIBS_INIT pthread) include(EthCompilerSettings) diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake index 3dd7fa798..1d1cb887b 100644 --- a/cmake/EthExecutableHelper.cmake +++ b/cmake/EthExecutableHelper.cmake @@ -45,26 +45,25 @@ endmacro() macro(eth_copy_dlls EXECUTABLE DLLS) # dlls must be unsubstitud list variable (without ${}) in format - # optimized;path_to_dll.dll;debug;path_to_dlld.dll + # optimized;path_to_dll.dll;debug;path_to_dlld.dll list(GET ${DLLS} 1 DLL_RELEASE) list(GET ${DLLS} 3 DLL_DEBUG) - get_target_property(TARGET_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE} RUNTIME_OUTPUT_DIRECTORY) add_custom_command(TARGET ${EXECUTABLE} - POST_BUILD - COMMAND ${CMAKE_COMMAND} ARGS - -DDLL_RELEASE="${DLL_RELEASE}" - -DDLL_DEBUG="${DLL_DEBUG}" + POST_BUILD + COMMAND ${CMAKE_COMMAND} ARGS + -DDLL_RELEASE="${DLL_RELEASE}" + -DDLL_DEBUG="${DLL_DEBUG}" -DCONF="$" - -DDESTINATION="${TARGET_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}" + -DDESTINATION="${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" -P "${ETH_SCRIPTS_DIR}/copydlls.cmake" ) endmacro() -# +# # this function requires the following variables to be specified: # ETH_DEPENDENCY_INSTALL_DIR # -# params: +# params: # QMLDIR # @@ -75,7 +74,7 @@ macro(eth_install_executable EXECUTABLE) set (one_value_args QMLDIR) set (multi_value_args DLLS) cmake_parse_arguments (ETH_INSTALL_EXECUTABLE "${options}" "${one_value_args}" "${multi_value_args}" "${extra_macro_args}") - + if (ETH_INSTALL_EXECUTABLE_QMLDIR) if (APPLE) set(eth_qml_dir "-qmldir=${ETH_INSTALL_EXECUTABLE_QMLDIR}") @@ -88,15 +87,19 @@ macro(eth_install_executable EXECUTABLE) if (APPLE) # First have qt5 install plugins and frameworks add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND ${MACDEPLOYQT_APP} ${EXECUTABLE}.app -executable=${EXECUTABLE}.app/Contents/MacOS/${EXECUTABLE} ${eth_qml_dir} - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR} - COMMAND sh ${CMAKE_SOURCE_DIR}/macdeployfix.sh ${EXECUTABLE}.app/Contents + COMMAND ${MACDEPLOYQT_APP} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app -executable=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app/Contents/MacOS/${EXECUTABLE} ${eth_qml_dir} + WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + COMMAND sh ${CMAKE_SOURCE_DIR}/macdeployfix.sh ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.app/Contents ) - - # TODO: This should only happen for GUI application - set(APP_BUNDLE_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INDIR}/${EXECUTABLE}.app") - + # This tool and next will inspect linked libraries in order to determine which dependencies are required + if (${CMAKE_CFG_INTDIR} STREQUAL ".") + # TODO: This should only happen for GUI application + set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}.app") + else () + set(APP_BUNDLE_PATH "${CMAKE_CURRENT_BINARY_DIR}/\$ENV{CONFIGURATION}/${EXECUTABLE}.app") + endif () + install(CODE " include(BundleUtilities) set(BU_CHMOD_BUNDLE_ITEMS 1) @@ -108,15 +111,14 @@ macro(eth_install_executable EXECUTABLE) get_target_property(TARGET_LIBS ${EXECUTABLE} INTERFACE_LINK_LIBRARIES) string(REGEX MATCH "Qt5::Core" HAVE_QT ${TARGET_LIBS}) if ("${HAVE_QT}" STREQUAL "Qt5::Core") - get_target_property(TARGET_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE} RUNTIME_OUTPUT_DIRECTORY) add_custom_command(TARGET ${EXECUTABLE} POST_BUILD - COMMAND cmd /C "set PATH=${Qt5Core_DIR}/../../../bin;%PATH% && ${WINDEPLOYQT_APP} ${TARGET_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.exe ${eth_qml_dir}" + COMMAND cmd /C "set PATH=${Qt5Core_DIR}/../../../bin;%PATH% && ${WINDEPLOYQT_APP} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${EXECUTABLE}.exe ${eth_qml_dir}" WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ) #workaround for https://bugreports.qt.io/browse/QTBUG-42083 add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND cmd /C "(echo [Paths] & echo.Prefix=.)" > "qt.conf" - WORKING_DIRECTORY ${TARGET_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR} VERBATIM + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} VERBATIM ) endif() @@ -142,3 +144,5 @@ macro(eth_install_executable EXECUTABLE) endif () endmacro() + + diff --git a/cmake/scripts/copydlls.cmake b/cmake/scripts/copydlls.cmake index 57eb0ffd4..6d86b8e4e 100644 --- a/cmake/scripts/copydlls.cmake +++ b/cmake/scripts/copydlls.cmake @@ -14,4 +14,5 @@ else () # Debug set(DLL ${DLL_DEBUG}) endif() -execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${DLL}" "${DESTINATION}") +execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${DLL}" "${DESTINATION}") + diff --git a/libevmasm/CMakeLists.txt b/libevmasm/CMakeLists.txt index eb8fea95c..f8150806f 100644 --- a/libevmasm/CMakeLists.txt +++ b/libevmasm/CMakeLists.txt @@ -19,10 +19,15 @@ set(EXECUTABLE evmasm) file(GLOB HEADERS "*.h") -add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) +if (ETH_STATIC) + add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS}) +else() + add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS}) +endif() target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcrypto) install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bedbe42f3..39a235c58 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -95,12 +95,6 @@ if (JSONRPC) target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARIES}) endif() -if (UNIX) # Create symlink to old testeth location to make bildbot happy - add_custom_command(TARGET testeth POST_BUILD - COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_BINARY_DIR}/bin/testeth ${CMAKE_BINARY_DIR}/test/testeth - ) -endif() - enable_testing() set(CTEST_OUTPUT_ON_FAILURE TRUE) @@ -116,6 +110,7 @@ eth_add_test(ClientBase ) eth_add_test(JsonRpc - ARGS --eth_testfile=BlockTests/bcJS_API_Test + ARGS --eth_testfile=BlockTests/bcJS_API_Test ARGS --eth_testfile=BlockTests/bcValidBlockTest ) + From 44c3e7b914224b92a47b2e6f9904b053891fe828 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 13 May 2015 10:59:26 +0200 Subject: [PATCH 048/157] libjsonconsole fix --- eth/main.cpp | 2 +- libjsconsole/JSConsole.cpp | 5 ++--- libjsconsole/JSConsole.h | 4 +++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index abb78c20d..387ae3be7 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -1765,7 +1765,7 @@ int main(int argc, char** argv) if (useConsole) { #if ETH_JSCONSOLE - JSConsole console(web3, vector({sigKey})); + JSConsole console(web3, make_shared([&](){return web3.ethereum();}, getAccountPassword, keyManager)); while (!g_exit) { console.repl(); diff --git a/libjsconsole/JSConsole.cpp b/libjsconsole/JSConsole.cpp index 791df2de4..d1f7c0264 100644 --- a/libjsconsole/JSConsole.cpp +++ b/libjsconsole/JSConsole.cpp @@ -25,7 +25,6 @@ #include #include "JSConsole.h" #include "JSV8Connector.h" -#include "libjsconsole/JSConsoleResources.hpp" // TODO! make readline optional! #include @@ -35,12 +34,12 @@ using namespace std; using namespace dev; using namespace dev::eth; -JSConsole::JSConsole(WebThreeDirect& _web3, std::vector const& _accounts): +JSConsole::JSConsole(WebThreeDirect& _web3, shared_ptr 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)); + m_jsonrpcServer.reset(new WebThreeStubServer(*m_jsonrpcConnector.get(), _web3, _accounts, vector())); } JSConsole::~JSConsole() {} diff --git a/libjsconsole/JSConsole.h b/libjsconsole/JSConsole.h index 3b65691f6..b7aded4f3 100644 --- a/libjsconsole/JSConsole.h +++ b/libjsconsole/JSConsole.h @@ -33,10 +33,12 @@ namespace dev namespace eth { +class AccountHolder; + class JSConsole { public: - JSConsole(WebThreeDirect& _web3, std::vector const& _accounts); + JSConsole(WebThreeDirect& _web3, std::shared_ptr const& _accounts); ~JSConsole(); void repl() const; From be5aa3dbf0c3997c8d90cf92ff5a9fba69fc7c59 Mon Sep 17 00:00:00 2001 From: subtly Date: Wed, 13 May 2015 11:03:05 +0200 Subject: [PATCH 049/157] cleanup --- libp2p/Common.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libp2p/Common.h b/libp2p/Common.h index e70d671b2..3029bf18a 100644 --- a/libp2p/Common.h +++ b/libp2p/Common.h @@ -172,13 +172,13 @@ struct NodeIPEndpoint /// Setting true causes isAllowed to return true for all addresses. (Used by test fixtures) static bool test_allowLocal; - NodeIPEndpoint(): address(bi::address()), udpPort(0), tcpPort(0) {} + NodeIPEndpoint() = default; 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; - uint16_t tcpPort; + bi::address address = bi::address(); + uint16_t udpPort = 0; + uint16_t tcpPort = 0; operator bi::udp::endpoint() const { return std::move(bi::udp::endpoint(address, udpPort)); } operator bi::tcp::endpoint() const { return std::move(bi::tcp::endpoint(address, tcpPort)); } From f724508902350194053960ec052c2a11df6cc307 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 13 May 2015 10:57:40 +0200 Subject: [PATCH 050/157] Bump password size to 256 chars --- libdevcore/CommonIO.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libdevcore/CommonIO.cpp b/libdevcore/CommonIO.cpp index 10c53ddb9..d37f74db2 100644 --- a/libdevcore/CommonIO.cpp +++ b/libdevcore/CommonIO.cpp @@ -131,7 +131,7 @@ std::string dev::getPassword(std::string const& _prompt) #else struct termios oflags; struct termios nflags; - char password[128]; + char password[256]; // disable echo in the terminal tcgetattr(fileno(stdin), &oflags); @@ -148,9 +148,9 @@ std::string dev::getPassword(std::string const& _prompt) password[strlen(password) - 1] = 0; // restore terminal - if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { + if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) BOOST_THROW_EXCEPTION(ExternalFunctionFailure("tcsetattr")); - } + return password; #endif From 100066a66475ca60ead252644ab04391c7180a66 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 13 May 2015 13:54:17 +0200 Subject: [PATCH 051/157] fix for building OpenCL on some linux distributions --- cmake/FindOpenCL.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindOpenCL.cmake b/cmake/FindOpenCL.cmake index 4d3ed842c..a786e2e86 100644 --- a/cmake/FindOpenCL.cmake +++ b/cmake/FindOpenCL.cmake @@ -118,7 +118,7 @@ if(WIN32) endif() else() find_library(OpenCL_LIBRARY - NAMES OpenCL) + NAMES OpenCL libOpenCL.so.1) endif() set(OpenCL_LIBRARIES ${OpenCL_LIBRARY}) From 5cac25e2efa8844a38a1a24b52751be71799b4d4 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 13 May 2015 15:45:12 +0300 Subject: [PATCH 052/157] Fix mining. --- ethminer/main.cpp | 27 +++++++++++++++++++++------ libethcore/Ethash.cpp | 9 ++++----- libethcore/Ethash.h | 1 - 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/ethminer/main.cpp b/ethminer/main.cpp index 124d3f779..80895c975 100644 --- a/ethminer/main.cpp +++ b/ethminer/main.cpp @@ -223,6 +223,7 @@ void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod) (void)_recheckPeriod; #if ETH_JSONRPC || !ETH_TRUE jsonrpc::HttpClient client(_remote); + Farm rpc(client); GenericFarm f; if (_m == MinerType::CPU) @@ -254,17 +255,31 @@ void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod) current.headerHash = hh; current.seedHash = h256(v[1].asString()); current.boundary = h256(fromHex(v[2].asString()), h256::AlignRight); - cnote << "Got work package:" << current.headerHash << " < " << current.boundary; + cnote << "Got work package:"; + cnote << " Header-hash:" << current.headerHash.hex(); + cnote << " Seedhash:" << current.seedHash.hex(); + cnote << " Target: " << h256(current.boundary).hex(); f.setWork(current); } this_thread::sleep_for(chrono::milliseconds(_recheckPeriod)); } - cnote << "Solution found; submitting [" << solution.nonce << "," << current.headerHash << "," << solution.mixHash << "] to" << _remote << "..."; - bool ok = rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(current.headerHash), "0x" + toString(solution.mixHash)); - if (ok) - clog(HappyChannel) << "Submitted and accepted."; + cnote << "Solution found; Submitting to" << _remote << "..."; + cnote << " Nonce:" << solution.nonce.hex(); + cnote << " Mixhash:" << solution.mixHash.hex(); + cnote << " Header-hash:" << current.headerHash.hex(); + cnote << " Seedhash:" << current.seedHash.hex(); + cnote << " Target: " << h256(current.boundary).hex(); + cnote << " Ethash: " << h256(EthashAux::eval(EthashAux::number(current.seedHash), current.headerHash, solution.nonce).value).hex(); + if (EthashAux::eval(EthashAux::number(current.seedHash), current.headerHash, solution.nonce).value < current.boundary) + { + bool ok = rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(current.headerHash), "0x" + toString(solution.mixHash)); + if (ok) + clog(HappyChannel) << "Submitted and accepted."; + else + clog(SadChannel) << "Not accepted."; + } else - clog(SadChannel) << "Not accepted."; + cwarn << "FAILURE: GPU gave incorrect result!"; current.reset(); } catch (jsonrpc::JsonRpcException&) diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 3724d8255..1a8355fdf 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -72,7 +72,6 @@ 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; } @@ -135,7 +134,7 @@ void Ethash::CPUMiner::workLoop() WorkPackage w = work(); - auto dag = EthashAux::full(w.blockNumber); + auto dag = EthashAux::full(EthashAux::number(w.seedHash)); h256 boundary = w.boundary; unsigned hashCount = 1; for (; !shouldStop(); tryNonce++, hashCount++) @@ -284,7 +283,7 @@ Ethash::GPUMiner::~GPUMiner() bool Ethash::GPUMiner::report(uint64_t _nonce) { Nonce n = (Nonce)(u64)_nonce; - Result r = EthashAux::eval(work().blockNumber, work().headerHash, n); + Result r = EthashAux::eval(EthashAux::number(work().seedHash), work().headerHash, n); if (r.value < work().boundary) return submitProof(Solution{n, r.mixHash}); return false; @@ -310,9 +309,9 @@ void Ethash::GPUMiner::workLoop() unsigned device = instances() > 1 ? index() : s_deviceId; - if (!EthashAux::computeFull(w.blockNumber)) + if (!EthashAux::computeFull(EthashAux::number(w.seedHash))) return; - EthashAux::FullType dag = EthashAux::full(w.blockNumber); + EthashAux::FullType dag = EthashAux::full(EthashAux::number(w.seedHash)); bytesConstRef dagData = dag->data(); m_miner->init(dagData.data(), dagData.size(), 32, s_platformId, device); } diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 82db15e87..997c32cd0 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -67,7 +67,6 @@ public: h256 boundary; h256 headerHash; ///< When h256() means "pause until notified a new work package is available". h256 seedHash; /// LTODO: IS this needed now that we use the block number instead? - uint64_t blockNumber; }; static const WorkPackage NullWorkPackage; From c7424bfce71b79f7eef458397c3f988f1ac0afea Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 13 May 2015 15:51:32 +0300 Subject: [PATCH 053/157] Version bump. --- libdevcore/Common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 6723ab76d..28b537be5 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -28,7 +28,7 @@ using namespace dev; namespace dev { -char const* Version = "0.9.19"; +char const* Version = "0.9.20"; const u256 UndefinedU256 = ~(u256)0; From 83650be2139734148ab1fc9882ff9e5074ac17ba Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 13 May 2015 16:34:37 +0300 Subject: [PATCH 054/157] Fix GPU mining in ethminer. --- libethcore/Ethash.cpp | 8 +++++++- libethcore/EthashAux.cpp | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 1a8355fdf..80550886c 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -300,6 +300,7 @@ void Ethash::GPUMiner::workLoop() // take local copy of work since it may end up being overwritten by kickOff/pause. try { WorkPackage w = work(); + cnote << "workLoop" << !!m_miner << m_minerSeed << w.seedHash; if (!m_miner || m_minerSeed != w.seedHash) { m_minerSeed = w.seedHash; @@ -309,7 +310,12 @@ void Ethash::GPUMiner::workLoop() unsigned device = instances() > 1 ? index() : s_deviceId; - if (!EthashAux::computeFull(EthashAux::number(w.seedHash))) + while (EthashAux::computeFull(EthashAux::number(w.seedHash)) != 100 && !shouldStop()) + { + cnote << "Awaiting DAG" << EthashAux::computeFull(EthashAux::number(w.seedHash)); + this_thread::sleep_for(chrono::milliseconds(500)); + } + if (shouldStop()) return; EthashAux::FullType dag = EthashAux::full(EthashAux::number(w.seedHash)); bytesConstRef dagData = dag->data(); diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index f7a0ac41d..9287bcbfc 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -170,7 +170,9 @@ EthashAux::FullType EthashAux::full(uint64_t _blockNumber, function(l->light, dagCallbackShim); + cnote << "Done loading."; DEV_GUARDED(get()->x_fulls) get()->m_fulls[seedHash] = get()->m_lastUsedFull = ret; @@ -192,7 +194,9 @@ unsigned EthashAux::computeFull(uint64_t _blockNumber) get()->m_fullProgress = 0; get()->m_generatingFullNumber = _blockNumber / ETHASH_EPOCH_LENGTH * ETHASH_EPOCH_LENGTH; get()->m_fullGenerator = unique_ptr(new thread([=](){ + cnote << "Loading full DAG of" << _blockNumber; get()->full(_blockNumber, [](unsigned p){ get()->m_fullProgress = p; return 0; }); + cnote << "Full DAG loaded"; get()->m_fullProgress = 0; get()->m_generatingFullNumber = NotGenerating; })); From de8c7e1c5d3379ff122cd51adcffb71231d373c0 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 13 May 2015 16:35:16 +0300 Subject: [PATCH 055/157] newaccount in eth. fix importing old accounts and guarantee wallet has at least one key in it. --- eth/main.cpp | 48 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index abb78c20d..1eed535cd 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -93,6 +93,7 @@ void interactiveHelp() << " mineforce Forces mining, even when there are no transactions." << endl << " block Gives the current block height." << endl << " accounts Gives information on all owned accounts (balances, mining beneficiary and default signer)." << endl + << " newaccount Creates a new account with the given name." << 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 @@ -1002,12 +1003,6 @@ 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); @@ -1104,6 +1099,16 @@ int main(int argc, char** argv) keyManager.create(masterPassword); } + for (auto const& s: toImport) + { + keyManager.import(s, "Imported key (UNSAFE)"); + if (!signingKey) + signingKey = toAddress(s); + } + + if (keyManager.accounts().empty()) + keyManager.import(Secret::random(), "Default key"); + auto toNumber = [&](string const& s) -> unsigned { if (s == "latest") return web3.ethereum()->number(); @@ -1368,9 +1373,36 @@ int main(int argc, char** argv) << std::chrono::duration_cast(it.lastPing).count() << "ms" << endl; } - else if (c && cmd == "balance") + else if (cmd == "newaccount") + { + string name; + std::getline(iss, name); + auto s = Secret::random(); + string password; + while (password.empty()) + { + password = getPassword("Please enter a password to protect this key (press enter for protection only be the MASTER password/keystore): "); + string confirm = getPassword("Please confirm the password by entering it again: "); + if (password != confirm) + { + cout << "Passwords were different. Try again." << endl; + password.clear(); + } + } + if (!password.empty()) + { + cout << "Enter a hint for this password: " << flush; + string hint; + std::getline(cin, hint); + keyManager.import(s, name, password, hint); + } + else + keyManager.import(s, name); + cout << "New account created: " << toAddress(s); + } + else if (c && cmd == "accounts") { - cout << "Current balance:" << endl; + cout << "Accounts:" << endl; u256 total = 0; for (auto const& i: keyManager.accountDetails()) { From fb7c6a10c0814b24ca59d9a7446ab2a8e4957fbb Mon Sep 17 00:00:00 2001 From: subtly Date: Wed, 13 May 2015 16:43:42 +0200 Subject: [PATCH 056/157] Bump ideal peer count based on network simulations. See also https://github.com/ethereum/devp2p/wiki/Peer-Selection-Strategy --- eth/main.cpp | 2 +- libp2p/Host.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index abb78c20d..1c553885c 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -547,7 +547,7 @@ int main(int argc, char** argv) string publicIP; string remoteHost; unsigned short remotePort = 30303; - unsigned peers = 5; + unsigned peers = 11; bool bootstrap = false; unsigned networkId = 0; diff --git a/libp2p/Host.h b/libp2p/Host.h index 4cfca7718..78dc50727 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -243,7 +243,7 @@ private: std::list> m_connecting; ///< Pending connections. Mutex x_connecting; ///< Mutex for m_connecting. - unsigned m_idealPeerCount = 5; ///< Ideal number of peers to be connected to. + unsigned m_idealPeerCount = 11; ///< Ideal number of peers to be connected to. std::map> m_capabilities; ///< Each of the capabilities we support. From 09bc520f7b7cc8a09f9d45e1481e2d716a895d74 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 12 May 2015 21:27:04 +0200 Subject: [PATCH 057/157] Known state: store tags on stack as unions. --- libevmasm/CommonSubexpressionEliminator.cpp | 9 +- libevmasm/ControlFlowGraph.cpp | 51 ++++++------ libevmasm/ControlFlowGraph.h | 4 - libevmasm/ExpressionClasses.cpp | 10 +++ libevmasm/ExpressionClasses.h | 6 +- libevmasm/KnownState.cpp | 92 +++++++++++++++------ libevmasm/KnownState.h | 19 +++-- test/libsolidity/SolidityOptimizer.cpp | 43 ++++++++++ 8 files changed, 168 insertions(+), 66 deletions(-) diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index e369c9dbc..7564fcd99 100644 --- a/libevmasm/CommonSubexpressionEliminator.cpp +++ b/libevmasm/CommonSubexpressionEliminator.cpp @@ -153,7 +153,9 @@ AssemblyItems CSECodeGenerator::generateCode( assertThrow(!m_classPositions[targetItem.second].empty(), OptimizerException, ""); if (m_classPositions[targetItem.second].count(targetItem.first)) continue; - SourceLocation const& location = m_expressionClasses.representative(targetItem.second).item->getLocation(); + SourceLocation location; + if (m_expressionClasses.representative(targetItem.second).item) + location = m_expressionClasses.representative(targetItem.second).item->getLocation(); int position = classElementPosition(targetItem.second); if (position < targetItem.first) // it is already at its target, we need another copy @@ -197,7 +199,9 @@ void CSECodeGenerator::addDependencies(Id _c) addDependencies(argument); m_neededBy.insert(make_pair(argument, _c)); } - if (expr.item->type() == Operation && ( + if ( + expr.item && + expr.item->type() == Operation && ( expr.item->instruction() == Instruction::SLOAD || expr.item->instruction() == Instruction::MLOAD || expr.item->instruction() == Instruction::SHA3 @@ -288,6 +292,7 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced) OptimizerException, "Sequence constrained operation requested out of sequence." ); + assertThrow(expr.item, OptimizerException, "Non-generated expression without item."); vector const& arguments = expr.arguments; for (Id arg: boost::adaptors::reverse(arguments)) generateClassElement(arg); diff --git a/libevmasm/ControlFlowGraph.cpp b/libevmasm/ControlFlowGraph.cpp index cc68b2af8..3566bdb17 100644 --- a/libevmasm/ControlFlowGraph.cpp +++ b/libevmasm/ControlFlowGraph.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -217,7 +218,6 @@ 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())}); @@ -238,8 +238,6 @@ void ControlFlowGraph::gatherKnowledge() } 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; @@ -254,22 +252,29 @@ void ControlFlowGraph::gatherKnowledge() 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 + set tags = state->tagsInExpression( + state->stackElement(state->stackHeight(), SourceLocation()) ); state->feedItem(m_items.at(pc++)); - if (nextBlock) - workQueue.push_back(make_pair(nextBlock, state->copy())); - else if (!unknownJumpEncountered) + + if (tags.empty() || std::any_of(tags.begin(), tags.end(), [&](u256 const& _tag) + { + return !m_blocks.count(BlockId(_tag)); + })) { - // 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())); + if (!unknownJumpEncountered) + { + // We do not know the target of this jump, 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 + for (auto tag: tags) + workQueue.push_back(make_pair(BlockId(tag), state->copy())); } else if (block.begin <= pc && pc < block.end) state->feedItem(m_items.at(pc++)); @@ -329,7 +334,11 @@ BasicBlocks ControlFlowGraph::rebuildCode() if (previousHandedOver && !pushes[blockId] && m_items[block.begin].type() == Tag) ++block.begin; if (block.begin < block.end) + { blocks.push_back(block); + blocks.back().startState->clearTagUnions(); + blocks.back().endState->clearTagUnions(); + } previousHandedOver = (block.endType == BasicBlock::EndType::HANDOVER); } } @@ -337,18 +346,6 @@ BasicBlocks ControlFlowGraph::rebuildCode() 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() { BlockId id = BlockId(++m_lastUsedId); diff --git a/libevmasm/ControlFlowGraph.h b/libevmasm/ControlFlowGraph.h index 3366dc45f..4480ba491 100644 --- a/libevmasm/ControlFlowGraph.h +++ b/libevmasm/ControlFlowGraph.h @@ -108,10 +108,6 @@ private: void setPrevLinks(); 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(); unsigned m_lastUsedId = 0; diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp index cfbeba7fa..81adc0dbb 100644 --- a/libevmasm/ExpressionClasses.cpp +++ b/libevmasm/ExpressionClasses.cpp @@ -82,6 +82,16 @@ ExpressionClasses::Id ExpressionClasses::find( return exp.id; } +ExpressionClasses::Id ExpressionClasses::newClass(SourceLocation const& _location) +{ + Expression exp; + exp.id = m_representatives.size(); + exp.item = storeItem(AssemblyItem(UndefinedItem, (u256(1) << 255) + exp.id, _location)); + m_representatives.push_back(exp); + m_expressions.insert(exp); + return exp.id; +} + bool ExpressionClasses::knownToBeDifferent(ExpressionClasses::Id _a, ExpressionClasses::Id _b) { // Try to simplify "_a - _b" and return true iff the value is a non-zero constant. diff --git a/libevmasm/ExpressionClasses.h b/libevmasm/ExpressionClasses.h index c83520300..dd94092e8 100644 --- a/libevmasm/ExpressionClasses.h +++ b/libevmasm/ExpressionClasses.h @@ -52,7 +52,8 @@ public: Id id; AssemblyItem const* item = nullptr; Ids arguments; - unsigned sequenceNumber; ///< Storage modification sequence, only used for SLOAD/SSTORE instructions. + /// Storage modification sequence, only used for storage and memory operations. + unsigned sequenceNumber = 0; /// Behaves as if this was a tuple of (item->type(), item->data(), arguments, sequenceNumber). bool operator<(Expression const& _other) const; }; @@ -73,6 +74,9 @@ public: /// @returns the number of classes. Id size() const { return m_representatives.size(); } + /// @returns the id of a new class which is different to all other classes. + Id newClass(SourceLocation const& _location); + /// @returns true if the values of the given classes are known to be different (on every input). /// @note that this function might still return false for some different inputs. bool knownToBeDifferent(Id _a, Id _b); diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index 5a70a74fb..b84e656aa 100644 --- a/libevmasm/KnownState.cpp +++ b/libevmasm/KnownState.cpp @@ -162,29 +162,41 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool /// Helper function for KnownState::reduceToCommonKnowledge, removes everything from /// _this which is not in or not equal to the value in _other. -template void intersect( - _Mapping& _this, - _Mapping const& _other, - function<_KeyType(_KeyType)> const& _keyTrans = [](_KeyType _k) { return _k; } -) +template void intersect(_Mapping& _this, _Mapping const& _other) { for (auto it = _this.begin(); it != _this.end();) - if (_other.count(_keyTrans(it->first)) && _other.at(_keyTrans(it->first)) == it->second) + if (_other.count(it->first) && _other.at(it->first) == it->second) ++it; else it = _this.erase(it); } -template void intersect(_Mapping& _this, _Mapping const& _other) -{ - intersect<_Mapping, ExpressionClasses::Id>(_this, _other, [](ExpressionClasses::Id _k) { return _k; }); -} - void KnownState::reduceToCommonKnowledge(KnownState const& _other) { int stackDiff = m_stackHeight - _other.m_stackHeight; - function stackKeyTransform = [=](int _key) -> int { return _key - stackDiff; }; - intersect(m_stackElements, _other.m_stackElements, stackKeyTransform); + for (auto it = m_stackElements.begin(); it != m_stackElements.end();) + if (_other.m_stackElements.count(it->first - stackDiff)) + { + Id other = _other.m_stackElements.at(it->first - stackDiff); + if (it->second == other) + ++it; + else + { + set theseTags = tagsInExpression(it->second); + set otherTags = tagsInExpression(other); + if (!theseTags.empty() && !otherTags.empty()) + { + theseTags.insert(otherTags.begin(), otherTags.end()); + it->second = tagUnion(theseTags); + ++it; + } + else + it = m_stackElements.erase(it); + } + } + else + it = m_stackElements.erase(it); + // Use the smaller stack height. Essential to terminate in case of loops. if (m_stackHeight > _other.m_stackHeight) { @@ -201,10 +213,15 @@ void KnownState::reduceToCommonKnowledge(KnownState const& _other) bool KnownState::operator==(const KnownState& _other) const { - return m_storageContent == _other.m_storageContent && - m_memoryContent == _other.m_memoryContent && - m_stackHeight == _other.m_stackHeight && - m_stackElements == _other.m_stackElements; + if (m_storageContent != _other.m_storageContent || m_memoryContent != _other.m_memoryContent) + return false; + int stackDiff = m_stackHeight - _other.m_stackHeight; + auto thisIt = m_stackElements.cbegin(); + auto otherIt = _other.m_stackElements.cbegin(); + for (; thisIt != m_stackElements.cend() && otherIt != _other.m_stackElements.cend(); ++thisIt, ++otherIt) + if (thisIt->first - stackDiff != otherIt->first || thisIt->second != otherIt->second) + return false; + return (thisIt == m_stackElements.cend() && otherIt == _other.m_stackElements.cend()); } ExpressionClasses::Id KnownState::stackElement(int _stackHeight, SourceLocation const& _location) @@ -212,18 +229,17 @@ ExpressionClasses::Id KnownState::stackElement(int _stackHeight, SourceLocation 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); + return m_stackElements[_stackHeight] = + m_expressionClasses->find(AssemblyItem(UndefinedItem, _stackHeight, _location)); } -ExpressionClasses::Id KnownState::initialStackElement( - int _stackHeight, - SourceLocation const& _location -) +void KnownState::clearTagUnions() { - // 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)); + for (auto it = m_stackElements.begin(); it != m_stackElements.end();) + if (m_tagUnions.left.count(it->second)) + it = m_stackElements.erase(it); + else + ++it; } void KnownState::setStackElement(int _stackHeight, Id _class) @@ -352,3 +368,27 @@ KnownState::Id KnownState::applySha3( return m_knownSha3Hashes[arguments] = v; } +set KnownState::tagsInExpression(KnownState::Id _expressionId) +{ + if (m_tagUnions.left.count(_expressionId)) + return m_tagUnions.left.at(_expressionId); + // Might be a tag, then return the set of itself. + ExpressionClasses::Expression expr = m_expressionClasses->representative(_expressionId); + if (expr.item && expr.item->type() == PushTag) + return set({expr.item->data()}); + else + return set(); +} + +KnownState::Id KnownState::tagUnion(set _tags) +{ + if (m_tagUnions.right.count(_tags)) + return m_tagUnions.right.at(_tags); + else + { + Id id = m_expressionClasses->newClass(SourceLocation()); + m_tagUnions.right.insert(make_pair(_tags, id)); + return id; + } +} + diff --git a/libevmasm/KnownState.h b/libevmasm/KnownState.h index f7a3dd675..3505df74f 100644 --- a/libevmasm/KnownState.h +++ b/libevmasm/KnownState.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -107,15 +108,16 @@ public: /// @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); + + /// @returns its set of tags if the given expression class is a known tag union; returns a set + /// containing the tag if it is a PushTag expression and the empty set otherwise. + std::set tagsInExpression(Id _expressionId); + /// During analysis, different tags on the stack are partially treated as the same class. + /// This removes such classes not to confuse later analyzers. + void clearTagUnions(); int stackHeight() const { return m_stackHeight; } std::map const& stackElements() const { return m_stackElements; } @@ -142,6 +144,9 @@ private: /// 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); + /// @returns a new or already used Id representing the given set of tags. + Id tagUnion(std::set _tags); + /// Current stack height, can be negative. int m_stackHeight = 0; /// Current stack layout, mapping stack height -> equivalence class @@ -157,6 +162,8 @@ private: std::map, Id> m_knownSha3Hashes; /// Structure containing the classes of equivalent expressions. std::shared_ptr m_expressionClasses; + /// Container for unions of tags stored on the stack. + boost::bimap> m_tagUnions; }; } diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index efc9316b0..ce43887e1 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -315,6 +315,49 @@ BOOST_AUTO_TEST_CASE(retain_information_in_branches) BOOST_CHECK_EQUAL(1, numSHA3s); } +BOOST_AUTO_TEST_CASE(store_tags_as_unions) +{ + // This calls the same function from two sources and both calls have a certain sha3 on + // the stack at the same position. + // Without storing tags as unions, the return from the shared function would not know where to + // jump and thus all jumpdests are forced to clear their state and we do not know about the + // sha3 anymore. + // Note that, for now, this only works if the functions have the same number of return + // parameters since otherwise, the return jump addresses are at different stack positions + // which triggers the "unknown jump target" situation. + char const* sourceCode = R"( + contract test { + bytes32 data; + function f(uint x, bytes32 y) external returns (uint r_a, bytes32 r_d) { + r_d = sha3(y); + shared(y); + r_d = sha3(y); + r_a = 5; + } + function g(uint x, bytes32 y) external returns (uint r_a, bytes32 r_d) { + r_d = sha3(y); + shared(y); + r_d = bytes32(uint(sha3(y)) + 2); + r_a = 7; + } + function shared(bytes32 y) internal { + data = sha3(y); + } + } + )"; + compileBothVersions(sourceCode); + compareVersions("f()", 7, "abc"); + + m_optimize = true; + bytes optimizedBytecode = compileAndRun(sourceCode, 0, "test"); + size_t numSHA3s = 0; + eth::eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) { + if (_instr == eth::Instruction::SHA3) + numSHA3s++; + }); + BOOST_CHECK_EQUAL(2, numSHA3s); +} + BOOST_AUTO_TEST_CASE(cse_intermediate_swap) { eth::KnownState state; From c094c3652efacdd20ea55440da2aeae4f7f8faee Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 13 May 2015 18:47:50 +0300 Subject: [PATCH 058/157] Fix defualt endpoint in ethminer. --- ethminer/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethminer/main.cpp b/ethminer/main.cpp index 80895c975..a322431b4 100644 --- a/ethminer/main.cpp +++ b/ethminer/main.cpp @@ -74,7 +74,7 @@ void help() << "Options:" << endl << endl #if ETH_JSONRPC || !ETH_TRUE << "Work farming mode:" << endl - << " -F,--farm Put into mining farm mode with the work server at URL (default: http://127.0.0.1:8080)" << endl + << " -F,--farm Put into mining farm mode with the work server at URL (default: http://127.0.0.1:8545)" << endl << " --farm-recheck Leave n ms between checks for changed work (default: 500)." << endl #endif << "Benchmarking mode:" << endl @@ -316,7 +316,7 @@ int main(int argc, char** argv) unsigned benchmarkTrials = 5; /// Farm params - string farmURL = "http://127.0.0.1:8080"; + string farmURL = "http://127.0.0.1:8545"; unsigned farmRecheckPeriod = 500; for (int i = 1; i < argc; ++i) From a508bb85ae93c03b8971d064602567f39c07cad7 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 13 May 2015 18:48:14 +0300 Subject: [PATCH 059/157] Fix default farm endpoint in eth. --- eth/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eth/main.cpp b/eth/main.cpp index 22556bac0..56c9c3534 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -579,7 +579,7 @@ int main(int argc, char** argv) bool useConsole = false; /// Farm params - string farmURL = "http://127.0.0.1:8080"; + string farmURL = "http://127.0.0.1:8545"; unsigned farmRecheckPeriod = 500; /// Wallet password stuff From 5cc63de2f969acbedbfbf52a3681657c57d92570 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 13 May 2015 18:02:20 +0200 Subject: [PATCH 060/157] Use seedhash everywhere in EthashAux We now use seedhash everywhere and generate a block number only where it's needed. Namely ethash_light_new() --- alethzero/MainWin.cpp | 6 ++++- eth/main.cpp | 4 ++-- ethminer/main.cpp | 8 +++---- libethcore/Ethash.cpp | 12 +++++----- libethcore/EthashAux.cpp | 48 +++++++++++++++++++--------------------- libethcore/EthashAux.h | 12 +++++----- 6 files changed, 46 insertions(+), 44 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 7551eaa35..619fc0637 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -945,7 +945,11 @@ void Main::on_preview_triggered() void Main::on_prepNextDAG_triggered() { - EthashAux::computeFull(ethereum()->blockChain().number() + ETHASH_EPOCH_LENGTH); + EthashAux::computeFull( + EthashAux::seedHash( + ethereum()->blockChain().number() + ETHASH_EPOCH_LENGTH + ) + ); } void Main::refreshMining() diff --git a/eth/main.cpp b/eth/main.cpp index 1eed535cd..e352cd53a 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -857,7 +857,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((uint64_t)bi.number, powHash, bi.nonce); + auto r = EthashAux::eval(bi.seedHash(), powHash, bi.nonce); bool valid = r.value < boundary; cout << (valid ? "VALID :-)" : "INVALID :-(") << endl; cout << r.value << (valid ? " < " : " >= ") << boundary << endl; @@ -866,7 +866,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((uint64_t)bi.number)->data()) << endl; + cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(bi)->data()) << endl; exit(0); } catch (...) diff --git a/ethminer/main.cpp b/ethminer/main.cpp index 80895c975..33c2e7c80 100644 --- a/ethminer/main.cpp +++ b/ethminer/main.cpp @@ -269,8 +269,8 @@ void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod) cnote << " Header-hash:" << current.headerHash.hex(); cnote << " Seedhash:" << current.seedHash.hex(); cnote << " Target: " << h256(current.boundary).hex(); - cnote << " Ethash: " << h256(EthashAux::eval(EthashAux::number(current.seedHash), current.headerHash, solution.nonce).value).hex(); - if (EthashAux::eval(EthashAux::number(current.seedHash), current.headerHash, solution.nonce).value < current.boundary) + cnote << " Ethash: " << h256(EthashAux::eval(current.seedHash, current.headerHash, solution.nonce).value).hex(); + if (EthashAux::eval(current.seedHash, current.headerHash, solution.nonce).value < current.boundary) { bool ok = rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(current.headerHash), "0x" + toString(solution.mixHash)); if (ok) @@ -432,7 +432,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((uint64_t)bi.number, powHash, bi.nonce); + auto r = EthashAux::eval(bi.seedHash(), powHash, bi.nonce); bool valid = r.value < boundary; cout << (valid ? "VALID :-)" : "INVALID :-(") << endl; cout << r.value << (valid ? " < " : " >= ") << boundary << endl; @@ -441,7 +441,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((uint64_t)bi.number)->data()) << endl; + cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(bi)->data()) << endl; exit(0); } catch (...) diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 80550886c..92f9d2e18 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -77,7 +77,7 @@ Ethash::WorkPackage Ethash::package(BlockInfo const& _bi) void Ethash::prep(BlockInfo const& _header, std::function const& _f) { - EthashAux::full((unsigned)_header.number, _f); + EthashAux::full(_header.seedHash(), _f); } bool Ethash::preVerify(BlockInfo const& _header) @@ -134,7 +134,7 @@ void Ethash::CPUMiner::workLoop() WorkPackage w = work(); - auto dag = EthashAux::full(EthashAux::number(w.seedHash)); + auto dag = EthashAux::full(w.seedHash); h256 boundary = w.boundary; unsigned hashCount = 1; for (; !shouldStop(); tryNonce++, hashCount++) @@ -283,7 +283,7 @@ Ethash::GPUMiner::~GPUMiner() bool Ethash::GPUMiner::report(uint64_t _nonce) { Nonce n = (Nonce)(u64)_nonce; - Result r = EthashAux::eval(EthashAux::number(work().seedHash), work().headerHash, n); + Result r = EthashAux::eval(work().seedHash, work().headerHash, n); if (r.value < work().boundary) return submitProof(Solution{n, r.mixHash}); return false; @@ -310,14 +310,14 @@ void Ethash::GPUMiner::workLoop() unsigned device = instances() > 1 ? index() : s_deviceId; - while (EthashAux::computeFull(EthashAux::number(w.seedHash)) != 100 && !shouldStop()) + while (EthashAux::computeFull(w.seedHash) != 100 && !shouldStop()) { - cnote << "Awaiting DAG" << EthashAux::computeFull(EthashAux::number(w.seedHash)); + cnote << "Awaiting DAG" << EthashAux::computeFull(w.seedHash); this_thread::sleep_for(chrono::milliseconds(500)); } if (shouldStop()) return; - EthashAux::FullType dag = EthashAux::full(EthashAux::number(w.seedHash)); + EthashAux::FullType dag = EthashAux::full(w.seedHash); bytesConstRef dagData = dag->data(); m_miner->init(dagData.data(), dagData.size(), 32, s_platformId, device); } diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index 9287bcbfc..4f29a6516 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -107,21 +107,21 @@ void EthashAux::killCache(h256 const& _s) EthashAux::LightType EthashAux::light(BlockInfo const& _header) { - return light((uint64_t)_header.number); + return light(_header.seedHash()); } -EthashAux::LightType EthashAux::light(uint64_t _blockNumber) +EthashAux::LightType EthashAux::light(h256 const& _seedHash) { RecursiveGuard l(get()->x_lights); - h256 seedHash = EthashAux::seedHash(_blockNumber); - LightType ret = get()->m_lights[seedHash]; - return ret ? ret : (get()->m_lights[seedHash] = make_shared(_blockNumber)); + LightType ret = get()->m_lights[_seedHash]; + return ret ? ret : (get()->m_lights[_seedHash] = make_shared(_seedHash)); } -EthashAux::LightAllocation::LightAllocation(uint64_t _blockNumber) +EthashAux::LightAllocation::LightAllocation(h256 const& _seedHash) { - light = ethash_light_new(_blockNumber); - size = ethash_get_cachesize(_blockNumber); + uint64_t blockNumber = EthashAux::number(_seedHash); + light = ethash_light_new(blockNumber); + size = ethash_get_cachesize(blockNumber); } EthashAux::LightAllocation::~LightAllocation() @@ -156,14 +156,13 @@ static int dagCallbackShim(unsigned _p) return s_dagCallback ? s_dagCallback(_p) : 0; } -EthashAux::FullType EthashAux::full(uint64_t _blockNumber, function const& _f) +EthashAux::FullType EthashAux::full(h256 const& _seedHash, function const& _f) { - auto l = light(_blockNumber); - h256 seedHash = EthashAux::seedHash(_blockNumber); FullType ret; + auto l = light(_seedHash); DEV_GUARDED(get()->x_fulls) - if ((ret = get()->m_fulls[seedHash].lock())) + if ((ret = get()->m_fulls[_seedHash].lock())) { get()->m_lastUsedFull = ret; return ret; @@ -175,15 +174,15 @@ EthashAux::FullType EthashAux::full(uint64_t _blockNumber, functionx_fulls) - get()->m_fulls[seedHash] = get()->m_lastUsedFull = ret; + get()->m_fulls[_seedHash] = get()->m_lastUsedFull = ret; return ret; } -unsigned EthashAux::computeFull(uint64_t _blockNumber) +unsigned EthashAux::computeFull(h256 const& _seedHash) { Guard l(get()->x_fulls); - h256 seedHash = EthashAux::seedHash(_blockNumber); - if (FullType ret = get()->m_fulls[seedHash].lock()) + uint64_t blockNumber = EthashAux::number(_seedHash); + if (FullType ret = get()->m_fulls[_seedHash].lock()) { get()->m_lastUsedFull = ret; return 100; @@ -192,17 +191,17 @@ unsigned EthashAux::computeFull(uint64_t _blockNumber) if (!get()->m_fullGenerator || !get()->m_fullGenerator->joinable()) { get()->m_fullProgress = 0; - get()->m_generatingFullNumber = _blockNumber / ETHASH_EPOCH_LENGTH * ETHASH_EPOCH_LENGTH; + get()->m_generatingFullNumber = blockNumber / ETHASH_EPOCH_LENGTH * ETHASH_EPOCH_LENGTH; get()->m_fullGenerator = unique_ptr(new thread([=](){ - cnote << "Loading full DAG of" << _blockNumber; - get()->full(_blockNumber, [](unsigned p){ get()->m_fullProgress = p; return 0; }); + cnote << "Loading full DAG of seedhash: " << _seedHash; + get()->full(_seedHash, [](unsigned p){ get()->m_fullProgress = p; return 0; }); cnote << "Full DAG loaded"; get()->m_fullProgress = 0; get()->m_generatingFullNumber = NotGenerating; })); } - return (get()->m_generatingFullNumber == _blockNumber) ? get()->m_fullProgress : 0; + return (get()->m_generatingFullNumber == blockNumber) ? get()->m_fullProgress : 0; } Ethash::Result EthashAux::FullAllocation::compute(h256 const& _headerHash, Nonce const& _nonce) const @@ -223,13 +222,12 @@ Ethash::Result EthashAux::LightAllocation::compute(h256 const& _headerHash, Nonc Ethash::Result EthashAux::eval(BlockInfo const& _header, Nonce const& _nonce) { - return eval((uint64_t)_header.number, _header.headerHash(WithoutNonce), _nonce); + return eval(_header.seedHash(), _header.headerHash(WithoutNonce), _nonce); } -Ethash::Result EthashAux::eval(uint64_t _blockNumber, h256 const& _headerHash, Nonce const& _nonce) +Ethash::Result EthashAux::eval(h256 const& _seedHash, h256 const& _headerHash, Nonce const& _nonce) { - h256 seedHash = EthashAux::seedHash(_blockNumber); - if (FullType dag = get()->m_fulls[seedHash].lock()) + if (FullType dag = get()->m_fulls[_seedHash].lock()) return dag->compute(_headerHash, _nonce); - return EthashAux::get()->light(_blockNumber)->compute(_headerHash, _nonce); + return EthashAux::get()->light(_seedHash)->compute(_headerHash, _nonce); } diff --git a/libethcore/EthashAux.h b/libethcore/EthashAux.h index f57f7a4d3..2a4060e78 100644 --- a/libethcore/EthashAux.h +++ b/libethcore/EthashAux.h @@ -40,7 +40,7 @@ public: struct LightAllocation { - LightAllocation(uint64_t _blockNumber); + LightAllocation(h256 const& _seedHash); ~LightAllocation(); bytesConstRef data() const; Ethash::Result compute(h256 const& _headerHash, Nonce const& _nonce) const; @@ -66,19 +66,19 @@ public: static uint64_t cacheSize(BlockInfo const& _header); static LightType light(BlockInfo const& _header); - static LightType light(uint64_t _blockNumber); + static LightType light(h256 const& _seedHash); static const uint64_t NotGenerating = (uint64_t)-1; - /// Kicks off generation of DAG for @a _blocknumber and @returns false or @returns true if ready. - static unsigned computeFull(uint64_t _blockNumber); + /// Kicks off generation of DAG for @a _seedHash and @returns false or @returns true if ready. + static unsigned computeFull(h256 const& _seedHash); /// Information on the generation progress. static std::pair fullGeneratingProgress() { return std::make_pair(get()->m_generatingFullNumber, get()->m_fullProgress); } /// Kicks off generation of DAG for @a _blocknumber and blocks until ready; @returns result. - static FullType full(uint64_t _blockNumber, std::function const& _f = std::function()); + static FullType full(h256 const& _seedHash, std::function const& _f = std::function()); 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(uint64_t _blockNumber, h256 const& _headerHash, Nonce const& _nonce); + static Ethash::Result eval(h256 const& _seedHash, h256 const& _headerHash, Nonce const& _nonce); private: EthashAux() {} From 8aaaae3d33ee003338153803641d369a670610fe Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 13 May 2015 18:18:47 +0200 Subject: [PATCH 061/157] Remove unneeded comment --- libethcore/Ethash.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 997c32cd0..0fd2e4cd0 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -66,7 +66,7 @@ public: h256 boundary; h256 headerHash; ///< When h256() means "pause until notified a new work package is available". - h256 seedHash; /// LTODO: IS this needed now that we use the block number instead? + h256 seedHash; }; static const WorkPackage NullWorkPackage; @@ -78,7 +78,7 @@ public: static bool preVerify(BlockInfo const& _header); static WorkPackage package(BlockInfo const& _header); static void assignResult(Solution const& _r, BlockInfo& _header) { _header.nonce = _r.nonce; _header.mixHash = _r.mixHash; } - + class CPUMiner: public Miner, Worker { @@ -119,7 +119,7 @@ public: static void setDefaultPlatform(unsigned _id) { s_platformId = _id; } static void setDefaultDevice(unsigned _id) { s_deviceId = _id; } static void setNumInstances(unsigned _instances) { s_numInstances = std::min(_instances, getNumDevices()); } - + protected: void kickOff() override; void pause() override; From dfdc1a44e9dc820f9931e9d17c0070386cfee0d7 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 13 May 2015 19:13:03 +0200 Subject: [PATCH 062/157] Fixed indentation. --- libevmasm/CommonSubexpressionEliminator.cpp | 4 +--- libevmasm/KnownState.cpp | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index 7564fcd99..9f6f9dd63 100644 --- a/libevmasm/CommonSubexpressionEliminator.cpp +++ b/libevmasm/CommonSubexpressionEliminator.cpp @@ -199,9 +199,7 @@ void CSECodeGenerator::addDependencies(Id _c) addDependencies(argument); m_neededBy.insert(make_pair(argument, _c)); } - if ( - expr.item && - expr.item->type() == Operation && ( + if (expr.item && expr.item->type() == Operation && ( expr.item->instruction() == Instruction::SLOAD || expr.item->instruction() == Instruction::MLOAD || expr.item->instruction() == Instruction::SHA3 diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index b84e656aa..0aac9cedb 100644 --- a/libevmasm/KnownState.cpp +++ b/libevmasm/KnownState.cpp @@ -230,7 +230,7 @@ ExpressionClasses::Id KnownState::stackElement(int _stackHeight, SourceLocation return m_stackElements.at(_stackHeight); // Stack element not found (not assigned yet), create new unknown equivalence class. return m_stackElements[_stackHeight] = - m_expressionClasses->find(AssemblyItem(UndefinedItem, _stackHeight, _location)); + m_expressionClasses->find(AssemblyItem(UndefinedItem, _stackHeight, _location)); } void KnownState::clearTagUnions() From b821f0e7dc66bcc1ed35ecbc46c84fe83562b192 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 13 May 2015 20:17:43 +0300 Subject: [PATCH 063/157] Fix build. --- libethash/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libethash/CMakeLists.txt b/libethash/CMakeLists.txt index 907eccd40..d6ae41569 100644 --- a/libethash/CMakeLists.txt +++ b/libethash/CMakeLists.txt @@ -43,6 +43,4 @@ if (CRYPTOPP_FOUND) TARGET_LINK_LIBRARIES(${LIBRARY} ${CRYPTOPP_LIBRARIES}) endif() -if (NOT ETHASHCL) - install( TARGETS ${LIBRARY} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) -endif () \ No newline at end of file +install( TARGETS ${LIBRARY} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) From 6b0007d98ec41b5de7237df0677ae8a06510608e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 13 May 2015 19:35:19 +0200 Subject: [PATCH 064/157] Add support for --singletest filter in VM tests. Add & correct arithmetic VM tests. --- .../VMTestsFiller/vmArithmeticTestFiller.json | 189 +++++++++++++++++- test/libevm/vm.cpp | 7 +- 2 files changed, 188 insertions(+), 8 deletions(-) diff --git a/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json b/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json index c06a429e0..76771982e 100644 --- a/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json +++ b/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json @@ -728,6 +728,41 @@ "gas" : "100000" } }, + + "divByZero_2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "storage" : { + "0x" : "0x00" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (+ (/ 13 0) 7)}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, "div1": { "env" : { @@ -974,6 +1009,34 @@ } }, + "sdivByZero2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (+ (SDIV (- 0 115792089237316195423570985008687907853269984665640564039457584007900129639935) 0) 1) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + "sdiv0": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", @@ -1639,6 +1702,34 @@ } }, + "modByZero": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (- (% 3 0) 1) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + "smod0": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", @@ -1873,7 +1964,7 @@ "value" : "1000000000000000000", "data" : "", "gasPrice" : "100000000000000", - "gas" : "10000" + "gas" : "100000" } }, @@ -1912,6 +2003,34 @@ } }, + "smod8_byZero": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (- (SMOD (- 0 200) 0) 13)}", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + "addmod0": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", @@ -2006,7 +2125,7 @@ "value" : "1000000000000000000", "data" : "", "gasPrice" : "100000000000000", - "gas" : "10000" + "gas" : "1000000" } }, @@ -2104,7 +2223,7 @@ "value" : "1000000000000000000", "data" : "", "gasPrice" : "100000000000000", - "gas" : "10000" + "gas" : "1000000" } }, @@ -2132,7 +2251,7 @@ "value" : "1000000000000000000", "data" : "", "gasPrice" : "100000000000000", - "gas" : "10000" + "gas" : "1000000" } }, @@ -2416,6 +2535,34 @@ } }, + "addmodDivByZero3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (- (ADDMOD 0 0 0) 1) } ", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + "mulmod0": { "env" : { @@ -2546,7 +2693,7 @@ "value" : "1000000000000000000", "data" : "", "gasPrice" : "100000000000000", - "gas" : "10000" + "gas" : "1000000" } }, @@ -2574,7 +2721,7 @@ "value" : "1000000000000000000", "data" : "", "gasPrice" : "100000000000000", - "gas" : "10000" + "gas" : "1000000" } }, @@ -2602,7 +2749,7 @@ "value" : "1000000000000000000", "data" : "", "gasPrice" : "100000000000000", - "gas" : "10000" + "gas" : "1000000" } }, @@ -2921,6 +3068,34 @@ } }, + "mulmoddivByZero3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (- 1 (MULMOD 0 0 0)) } ", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + "expXY": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", diff --git a/test/libevm/vm.cpp b/test/libevm/vm.cpp index 090258244..10670bfe3 100644 --- a/test/libevm/vm.cpp +++ b/test/libevm/vm.cpp @@ -300,9 +300,14 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) { for (auto& i: v.get_obj()) { - std::cout << " " << i.first << "\n"; mObject& o = i.second.get_obj(); + if (test::Options::get().singleTest && test::Options::get().singleTestName != i.first) + { + o.clear(); + continue; + } + std::cout << " " << i.first << "\n"; BOOST_REQUIRE(o.count("env") > 0); BOOST_REQUIRE(o.count("pre") > 0); BOOST_REQUIRE(o.count("exec") > 0); From 89dbcca30b752ecf2b8b56b5f396a6a86c29fc0a Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 14 May 2015 14:05:30 +0200 Subject: [PATCH 065/157] Squashed 'libjsqrc/ethereumjs/' changes from e908439..16861fc 16861fc version 0.4.2 e4f7dde fixed failing lint 69e7d9d fixed #133 55553d7 add async error test d02a375 Merge branch 'develop' of github.com:ethereum/web3.js into develop ff48da1 fixed callback error issue 471bce1 #133 in progress dc69085 version 0.4.1 2ae0afa critical bugfix 09f2a92 updated examples a0a36e5 Merge branch 'develop' of https://github.com/ethereum/ethereum.js into develop 2b179a8 updated node install test 8f63640 Merge pull request #203 from frozeman/develop 22ef4a1 added estimateGas method cd2e462 version 0.4.0 ae7762a Merge pull request #198 from ethereum/minerMethods d1e1206 removed byte formatter methods 6fd17d9 merged develop 373fd1b Merge pull request #201 from debris/batch 274fc29 Merge pull request #200 from debris/contract_overhaul b2ff2ff Merge branch 'contract_overhaul' into batch 99a3bda removed redundant lines 7cafac9 Merge branch 'develop' into contract_overhaul fa8db32 Merge pull request #202 from debris/async_properties 5f9272c asyncGet -> getAsync cd0df61 gulp 80c0792 async getting properties, remove property setters 744bb9e batch for requests with calls/transacts 8636077 initial support for batch requests a0b9cfb contract async call && transact 1272780 sendTransaction && call async 6afb1f9 Merge branch 'async-contract-calls' of https://github.com/niran/web3.js into contract_overhaul 611f640 asynchronous contract creation, breaking changes e3796bf merged develop edf808a add getWork and submitWork functions and toXBytes utils 9812b01 Merge branch 'blockFilterProposal' of https://github.com/ethereum/ethereum.js into develop 6f466f6 add miner functions 3af8e27 add newblockfilter Proposal e86552f Use async contract calls when a callback is passed git-subtree-dir: libjsqrc/ethereumjs git-subtree-split: 16861fc1944cca721672bb8faa81909d69be2b99 --- bower.json | 2 +- dist/web3-light.js | 591 +++++++++++++++++---------- dist/web3-light.js.map | 30 +- dist/web3-light.min.js | 4 +- dist/web3.js | 593 ++++++++++++++++++---------- dist/web3.js.map | 30 +- dist/web3.min.js | 4 +- example/contract.html | 44 ++- example/event_inc.html | 64 ++- example/node-app.js | 4 +- index.js | 1 - lib/solidity/abi.js | 44 --- lib/solidity/utils.js | 45 --- lib/utils/utils.js | 1 + lib/version.json | 2 +- lib/web3.js | 4 + lib/web3/batch.js | 61 +++ lib/web3/contract.js | 166 +++++--- lib/web3/eth.js | 23 ++ lib/web3/function.js | 89 ++++- lib/web3/method.js | 17 +- lib/web3/property.js | 40 +- lib/web3/requestmanager.js | 27 ++ lib/web3/watches.js | 15 +- package.js | 2 +- package.json | 2 +- test/abi.formatConstructorParams.js | 106 ----- test/async.js | 69 ++++ test/batch.js | 86 ++++ test/contract.js | 100 ++++- test/method.request.js | 23 ++ test/node/app.js | 2 +- test/node/package.json | 2 +- test/polling.js | 21 +- test/web3.eth.blockNumber.js | 20 + test/web3.eth.call.js | 41 ++ test/web3.eth.contract.js | 21 +- test/web3.eth.estimateGas.js | 25 ++ test/web3.eth.filter.js | 10 +- test/web3.eth.getWork.js | 16 + test/web3.eth.submitWork.js | 17 + 41 files changed, 1675 insertions(+), 789 deletions(-) delete mode 100644 lib/solidity/abi.js delete mode 100644 lib/solidity/utils.js create mode 100644 lib/web3/batch.js delete mode 100644 test/abi.formatConstructorParams.js create mode 100644 test/async.js create mode 100644 test/batch.js create mode 100644 test/method.request.js create mode 100644 test/web3.eth.call.js create mode 100644 test/web3.eth.estimateGas.js create mode 100644 test/web3.eth.getWork.js create mode 100644 test/web3.eth.submitWork.js diff --git a/bower.json b/bower.json index db9a4702d..ed620555f 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "web3", "namespace": "ethereum", - "version": "0.3.6", + "version": "0.4.2", "description": "Ethereum Compatible JavaScript API", "main": [ "./dist/web3.js", diff --git a/dist/web3-light.js b/dist/web3-light.js index c128634de..be6d95eec 100644 --- a/dist/web3-light.js +++ b/dist/web3-light.js @@ -15,52 +15,6 @@ require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof requ You should have received a copy of the GNU Lesser General Public License along with ethereum.js. If not, see . */ -/** - * @file abi.js - * @author Marek Kotewicz - * @author Gav Wood - * @date 2014 - */ - -var coder = require('./coder'); -var utils = require('./utils'); - -var formatConstructorParams = function (abi, params) { - 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 coder.encodeParams(constructor.inputs.map(function (input) { - return input.type; - }), params); -}; - -module.exports = { - formatConstructorParams: formatConstructorParams -}; - - -},{"./coder":2,"./utils":5}],2:[function(require,module,exports){ -/* - This file is part of ethereum.js. - - ethereum.js is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - ethereum.js 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with ethereum.js. If not, see . -*/ /** * @file coder.js * @author Marek Kotewicz @@ -328,7 +282,7 @@ var coder = new SolidityCoder([ module.exports = coder; -},{"../utils/utils":8,"./formatters":3,"./param":4,"bignumber.js":"bignumber.js"}],3:[function(require,module,exports){ +},{"../utils/utils":6,"./formatters":2,"./param":3,"bignumber.js":"bignumber.js"}],2:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -548,7 +502,7 @@ module.exports = { }; -},{"../utils/config":7,"../utils/utils":8,"./param":4,"bignumber.js":"bignumber.js"}],4:[function(require,module,exports){ +},{"../utils/config":5,"../utils/utils":6,"./param":3,"bignumber.js":"bignumber.js"}],3:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -760,54 +714,7 @@ SolidityParam.decodeArray = function (bytes, index) { module.exports = SolidityParam; -},{"../utils/utils":8}],5:[function(require,module,exports){ -/* - This file is part of ethereum.js. - - ethereum.js is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - ethereum.js 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with ethereum.js. If not, see . -*/ -/** - * @file utils.js - * @author Marek Kotewicz - * @date 2015 - */ - -/** - * Returns the contstructor with matching number of arguments - * - * @method getConstructor - * @param {Array} abi - * @param {Number} numberOfArgs - * @returns {Object} constructor function abi - */ -var getConstructor = function (abi, numberOfArgs) { - return abi.filter(function (f) { - return f.type === 'constructor' && f.inputs.length === numberOfArgs; - })[0]; -}; - -//var getSupremeType = function (type) { - //return type.substr(0, type.indexOf('[')) + ']'; -//}; - - -module.exports = { - getConstructor: getConstructor -}; - - -},{}],6:[function(require,module,exports){ +},{"../utils/utils":6}],4:[function(require,module,exports){ 'use strict'; // go env doesn't have and need XMLHttpRequest @@ -818,7 +725,7 @@ if (typeof XMLHttpRequest === 'undefined') { } -},{}],7:[function(require,module,exports){ +},{}],5:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -890,7 +797,7 @@ module.exports = { }; -},{"bignumber.js":"bignumber.js"}],8:[function(require,module,exports){ +},{"bignumber.js":"bignumber.js"}],6:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1256,6 +1163,7 @@ var toAddress = function (address) { return '0x' + padLeft(toHex(address).substr(2), 40); }; + /** * Returns true if object is BigNumber, otherwise false * @@ -1366,12 +1274,12 @@ module.exports = { }; -},{"bignumber.js":"bignumber.js"}],9:[function(require,module,exports){ +},{"bignumber.js":"bignumber.js"}],7:[function(require,module,exports){ module.exports={ - "version": "0.3.6" + "version": "0.4.2" } -},{}],10:[function(require,module,exports){ +},{}],8:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1411,6 +1319,7 @@ var RequestManager = require('./web3/requestmanager'); var c = require('./utils/config'); var Method = require('./web3/method'); var Property = require('./web3/property'); +var Batch = require('./web3/batch'); var web3Methods = [ new Method({ @@ -1503,6 +1412,9 @@ web3.toBigNumber = utils.toBigNumber; web3.toWei = utils.toWei; web3.fromWei = utils.fromWei; web3.isAddress = utils.isAddress; +web3.createBatch = function () { + return new Batch(); +}; // ADD defaultblock Object.defineProperty(web3.eth, 'defaultBlock', { @@ -1538,7 +1450,70 @@ setupMethods(web3.shh, shh.methods); module.exports = web3; -},{"./utils/config":7,"./utils/utils":8,"./version.json":9,"./web3/db":12,"./web3/eth":14,"./web3/filter":16,"./web3/formatters":17,"./web3/method":21,"./web3/net":22,"./web3/property":23,"./web3/requestmanager":25,"./web3/shh":26,"./web3/watches":27}],11:[function(require,module,exports){ +},{"./utils/config":5,"./utils/utils":6,"./version.json":7,"./web3/batch":9,"./web3/db":11,"./web3/eth":13,"./web3/filter":15,"./web3/formatters":16,"./web3/method":20,"./web3/net":21,"./web3/property":22,"./web3/requestmanager":24,"./web3/shh":25,"./web3/watches":26}],9:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** + * @file batch.js + * @author Marek Kotewicz + * @date 2015 + */ + +var RequestManager = require('./requestmanager'); + +var Batch = function () { + this.requests = []; +}; + +/** + * Should be called to add create new request to batch request + * + * @method add + * @param {Object} jsonrpc requet object + */ +Batch.prototype.add = function (request) { + this.requests.push(request); +}; + +/** + * Should be called to execute batch request + * + * @method execute + */ +Batch.prototype.execute = function () { + var requests = this.requests; + RequestManager.getInstance().sendBatch(requests, function (err, results) { + results = results || []; + requests.map(function (request, index) { + return results[index] || {}; + }).map(function (result, index) { + return requests[index].format ? requests[index].format(result.result) : result.result; + }).forEach(function (result, index) { + if (requests[index].callback) { + requests[index].callback(err, result); + } + }); + }); +}; + +module.exports = Batch; + + +},{"./requestmanager":24}],10:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1562,13 +1537,39 @@ module.exports = web3; */ var web3 = require('../web3'); -var solAbi = require('../solidity/abi'); var utils = require('../utils/utils'); +var coder = require('../solidity/coder'); var SolidityEvent = require('./event'); var SolidityFunction = require('./function'); -var addFunctionsToContract = function (contract, desc) { - desc.filter(function (json) { +/** + * Should be called to encode constructor params + * + * @method encodeConstructorParams + * @param {Array} abi + * @param {Array} constructor params + */ +var encodeConstructorParams = function (abi, params) { + return abi.filter(function (json) { + return json.type === 'constructor' && json.inputs.length === params.length; + }).map(function (json) { + return json.inputs.map(function (input) { + return input.type; + }); + }).map(function (types) { + return coder.encodeParams(types, params); + })[0] || ''; +}; + +/** + * Should be called to add functions to contract object + * + * @method addFunctionsToContract + * @param {Contract} contract + * @param {Array} abi + */ +var addFunctionsToContract = function (contract, abi) { + abi.filter(function (json) { return json.type === 'function'; }).map(function (json) { return new SolidityFunction(json, contract.address); @@ -1577,8 +1578,15 @@ var addFunctionsToContract = function (contract, desc) { }); }; -var addEventsToContract = function (contract, desc) { - desc.filter(function (json) { +/** + * Should be called to add events to contract object + * + * @method addEventsToContract + * @param {Contract} contract + * @param {Array} abi + */ +var addEventsToContract = function (contract, abi) { + abi.filter(function (json) { return json.type === 'event'; }).map(function (json) { return new SolidityEvent(json, contract.address); @@ -1588,65 +1596,106 @@ var addEventsToContract = function (contract, desc) { }; /** - * This method should be called when we want to call / transact some solidity method from javascript - * it returns an object which has same methods available as solidity contract description - * usage example: - * - * var abi = [{ - * name: 'myMethod', - * inputs: [{ name: 'a', type: 'string' }], - * outputs: [{name: 'd', type: 'string' }] - * }]; // contract abi - * - * var MyContract = web3.eth.contract(abi); // creation of contract prototype - * - * var contractInstance = new MyContract('0x0123123121'); + * Should be called to create new ContractFactory * - * contractInstance.myMethod('this is test string param for call'); // myMethod call (implicit, default) - * contractInstance.call().myMethod('this is test string param for call'); // myMethod call (explicit) - * contractInstance.sendTransaction().myMethod('this is test string param for transact'); // myMethod sendTransaction - * - * @param abi - abi json description of the contract, which is being created - * @returns contract object + * @method contract + * @param {Array} abi + * @returns {ContractFactory} new contract factory */ var contract = function (abi) { + return new ContractFactory(abi); +}; - // return prototype - return Contract.bind(null, abi); +/** + * Should be called to create new ContractFactory instance + * + * @method ContractFactory + * @param {Array} abi + */ +var ContractFactory = function (abi) { + this.abi = abi; }; -var Contract = function (abi, options) { +/** + * Should be called to create new contract on a blockchain + * + * @method new + * @param {Any} contract constructor param1 (optional) + * @param {Any} contract constructor param2 (optional) + * @param {Object} contract transaction object (required) + * @param {Function} callback + * @returns {Contract} returns contract if no callback was passed, + * otherwise calls callback function (err, contract) + */ +ContractFactory.prototype.new = function () { + // parse arguments + var options = {}; // required! + var callback; - this.address = ''; - if (utils.isAddress(options)) { - this.address = options; - } else { // is an object! - // TODO, parse the rest of the args - options = options || {}; - var args = Array.prototype.slice.call(arguments, 2); - var bytes = solAbi.formatConstructorParams(abi, args); - options.data += bytes; - this.address = web3.eth.sendTransaction(options); + var args = Array.prototype.slice.call(arguments); + if (utils.isFunction(args[args.length - 1])) { + callback = args.pop(); } - addFunctionsToContract(this, abi); - addEventsToContract(this, abi); + var last = args[args.length - 1]; + if (utils.isObject(last) && !utils.isArray(last)) { + options = args.pop(); + } + + // throw an error if there are no options + + var bytes = encodeConstructorParams(this.abi, args); + options.data += bytes; + + if (!callback) { + var address = web3.eth.sendTransaction(options); + return this.at(address); + } + + var self = this; + web3.eth.sendTransaction(options, function (err, address) { + if (err) { + callback(err); + } + self.at(address, callback); + }); }; -Contract.prototype.call = function () { - console.error('contract.call is deprecated'); - return this; +/** + * Should be called to get access to existing contract on a blockchain + * + * @method at + * @param {Address} contract address (required) + * @param {Function} callback {optional) + * @returns {Contract} returns contract if no callback was passed, + * otherwise calls callback function (err, contract) + */ +ContractFactory.prototype.at = function (address, callback) { + // TODO: address is required + + if (callback) { + callback(null, new Contract(this.abi, address)); + } + return new Contract(this.abi, address); }; -Contract.prototype.sendTransaction = function () { - console.error('contract.sendTransact is deprecated'); - return this; +/** + * Should be called to create new contract instance + * + * @method Contract + * @param {Array} abi + * @param {Address} contract address + */ +var Contract = function (abi, address) { + this.address = address; + addFunctionsToContract(this, abi); + addEventsToContract(this, abi); }; module.exports = contract; -},{"../solidity/abi":1,"../utils/utils":8,"../web3":10,"./event":15,"./function":18}],12:[function(require,module,exports){ +},{"../solidity/coder":1,"../utils/utils":6,"../web3":8,"./event":14,"./function":17}],11:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1704,7 +1753,7 @@ module.exports = { methods: methods }; -},{"./method":21}],13:[function(require,module,exports){ +},{"./method":20}],12:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1744,7 +1793,7 @@ module.exports = { }; -},{}],14:[function(require,module,exports){ +},{}],13:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1921,6 +1970,14 @@ var call = new Method({ inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter] }); +var estimateGas = new Method({ + name: 'estimateGas', + call: 'eth_estimateGas', + params: 1, + inputFormatter: [formatters.inputTransactionFormatter], + outputFormatter: utils.toDecimal +}); + var compileSolidity = new Method({ name: 'compile.solidity', call: 'eth_compileSolidity', @@ -1939,6 +1996,18 @@ var compileSerpent = new Method({ params: 1 }); +var submitWork = new Method({ + name: 'submitWork', + call: 'eth_submitWork', + params: 3 +}); + +var getWork = new Method({ + name: 'getWork', + call: 'eth_getWork', + params: 0 +}); + var methods = [ getBalance, getStorageAt, @@ -1952,10 +2021,13 @@ var methods = [ getTransactionFromBlock, getTransactionCount, call, + estimateGas, sendTransaction, compileSolidity, compileLLL, compileSerpent, + submitWork, + getWork ]; /// @returns an array of objects describing web3.eth api properties @@ -1998,7 +2070,7 @@ module.exports = { }; -},{"../utils/utils":8,"./formatters":17,"./method":21,"./property":23}],15:[function(require,module,exports){ +},{"../utils/utils":6,"./formatters":16,"./method":20,"./property":22}],14:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2194,7 +2266,7 @@ SolidityEvent.prototype.attachToContract = function (contract) { module.exports = SolidityEvent; -},{"../solidity/coder":2,"../utils/utils":8,"../web3":10,"./formatters":17}],16:[function(require,module,exports){ +},{"../solidity/coder":1,"../utils/utils":6,"../web3":8,"./formatters":16}],15:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2351,7 +2423,7 @@ Filter.prototype.get = function (callback) { module.exports = Filter; -},{"../utils/utils":8,"./formatters":17,"./requestmanager":25}],17:[function(require,module,exports){ +},{"../utils/utils":6,"./formatters":16,"./requestmanager":24}],16:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2571,7 +2643,7 @@ module.exports = { }; -},{"../utils/config":7,"../utils/utils":8}],18:[function(require,module,exports){ +},{"../utils/config":5,"../utils/utils":6}],17:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2588,7 +2660,7 @@ module.exports = { You should have received a copy of the GNU Lesser General Public License along with ethereum.js. If not, see . */ -/** +/** * @file function.js * @author Marek Kotewicz * @date 2015 @@ -2613,18 +2685,23 @@ var SolidityFunction = function (json, address) { this._address = address; }; +SolidityFunction.prototype.extractCallback = function (args) { + if (utils.isFunction(args[args.length - 1])) { + return args.pop(); // modify the args array! + } +}; + /** * Should be used to create payload from arguments * * @method toPayload - * @param {...} solidity function params + * @param {Array} solidity function params * @param {Object} optional payload options */ -SolidityFunction.prototype.toPayload = function () { - var args = Array.prototype.slice.call(arguments); +SolidityFunction.prototype.toPayload = function (args) { var options = {}; if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) { - options = args.pop(); + options = args[args.length - 1]; } options.to = this._address; options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args); @@ -2641,19 +2718,41 @@ SolidityFunction.prototype.signature = function () { return web3.sha3(web3.fromAscii(this._name)).slice(2, 10); }; + +SolidityFunction.prototype.unpackOutput = function (output) { + if (output === null) { + return; + } + + output = output.length >= 2 ? output.slice(2) : output; + var result = coder.decodeParams(this._outputTypes, output); + return result.length === 1 ? result[0] : result; +}; + /** - * Should be used to call function - * + * Calls a contract function. + * * @method call - * @param {Object} options + * @param {...Object} Contract function arguments + * @param {function} If the last argument is a function, the contract function + * call will be asynchronous, and the callback will be passed the + * error and result. * @return {String} output bytes */ SolidityFunction.prototype.call = function () { - var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); - var output = web3.eth.call(payload); - output = output.length >= 2 ? output.slice(2) : output; - var result = coder.decodeParams(this._outputTypes, output); - return result.length === 1 ? result[0] : result; + var args = Array.prototype.slice.call(arguments); + var callback = this.extractCallback(args); + var payload = this.toPayload(args); + + if (!callback) { + var output = web3.eth.call(payload); + return this.unpackOutput(output); + } + + var self = this; + web3.eth.call(payload, function (error, output) { + callback(error, self.unpackOutput(output)); + }); }; /** @@ -2663,8 +2762,16 @@ SolidityFunction.prototype.call = function () { * @param {Object} options */ SolidityFunction.prototype.sendTransaction = function () { - var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); - web3.eth.sendTransaction(payload); + var args = Array.prototype.slice.call(arguments); + var callback = this.extractCallback(args); + var payload = this.toPayload(args); + + if (!callback) { + web3.eth.sendTransaction(payload); + return; + } + + web3.eth.sendTransaction(payload, callback); }; /** @@ -2679,7 +2786,7 @@ SolidityFunction.prototype.displayName = function () { /** * Should be used to get function type name - * + * * @method typeName * @return {String} type name of the function */ @@ -2687,6 +2794,25 @@ SolidityFunction.prototype.typeName = function () { return utils.extractTypeName(this._name); }; +/** + * Should be called to get rpc requests from solidity function + * + * @method request + * @returns {Object} + */ +SolidityFunction.prototype.request = function () { + var args = Array.prototype.slice.call(arguments); + var callback = this.extractCallback(args); + var payload = this.toPayload(args); + var format = this.unpackOutput.bind(this); + + return { + callback: callback, + payload: payload, + format: format + }; +}; + /** * Should be called to execute function * @@ -2694,7 +2820,7 @@ SolidityFunction.prototype.typeName = function () { */ SolidityFunction.prototype.execute = function () { var transaction = !this._constant; - + // send transaction if (transaction) { return this.sendTransaction.apply(this, Array.prototype.slice.call(arguments)); @@ -2712,6 +2838,7 @@ SolidityFunction.prototype.execute = function () { */ SolidityFunction.prototype.attachToContract = function (contract) { var execute = this.execute.bind(this); + execute.request = this.request.bind(this); execute.call = this.call.bind(this); execute.sendTransaction = this.sendTransaction.bind(this); var displayName = this.displayName(); @@ -2724,7 +2851,7 @@ SolidityFunction.prototype.attachToContract = function (contract) { module.exports = SolidityFunction; -},{"../solidity/coder":2,"../utils/utils":8,"../web3":10}],19:[function(require,module,exports){ +},{"../solidity/coder":1,"../utils/utils":6,"../web3":8}],18:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2816,7 +2943,7 @@ HttpProvider.prototype.sendAsync = function (payload, callback) { module.exports = HttpProvider; -},{"./errors":13,"xmlhttprequest":6}],20:[function(require,module,exports){ +},{"./errors":12,"xmlhttprequest":4}],19:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2909,7 +3036,7 @@ Jsonrpc.prototype.toBatchPayload = function (messages) { module.exports = Jsonrpc; -},{}],21:[function(require,module,exports){ +},{}],20:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2966,7 +3093,6 @@ Method.prototype.extractCallback = function (args) { if (utils.isFunction(args[args.length - 1])) { return args.pop(); // modify the args array! } - return null; }; /** @@ -3019,6 +3145,7 @@ Method.prototype.formatOutput = function (result) { */ Method.prototype.attachToObject = function (obj) { var func = this.send.bind(this); + func.request = this.request.bind(this); func.call = this.call; // that's ugly. filter.js uses it var name = this.name.split('.'); if (name.length > 1) { @@ -3049,6 +3176,19 @@ Method.prototype.toPayload = function (args) { }; }; +/** + * Should be called to create pure JSONRPC request which can be used in batch request + * + * @method request + * @param {...} params + * @return {Object} jsonrpc request + */ +Method.prototype.request = function () { + var payload = this.toPayload(Array.prototype.slice.call(arguments)); + payload.format = this.formatOutput.bind(this); + return payload; +}; + /** * Should send request to the API * @@ -3061,7 +3201,7 @@ Method.prototype.send = function () { if (payload.callback) { var self = this; return RequestManager.getInstance().sendAsync(payload, function (err, result) { - payload.callback(null, self.formatOutput(result)); + payload.callback(err, self.formatOutput(result)); }); } return this.formatOutput(RequestManager.getInstance().send(payload)); @@ -3070,7 +3210,7 @@ Method.prototype.send = function () { module.exports = Method; -},{"../utils/utils":8,"./errors":13,"./requestmanager":25}],22:[function(require,module,exports){ +},{"../utils/utils":6,"./errors":12,"./requestmanager":24}],21:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3120,7 +3260,7 @@ module.exports = { }; -},{"../utils/utils":8,"./property":23}],23:[function(require,module,exports){ +},{"../utils/utils":6,"./property":22}],22:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3186,16 +3326,23 @@ Property.prototype.formatOutput = function (result) { Property.prototype.attachToObject = function (obj) { var proto = { get: this.get.bind(this), - set: this.set.bind(this) }; - var name = this.name.split('.'); - if (name.length > 1) { - obj[name[0]] = obj[name[0]] || {}; - Object.defineProperty(obj[name[0]], name[1], proto); - } else { - Object.defineProperty(obj, name[0], proto); + var names = this.name.split('.'); + var name = names[0]; + if (names.length > 1) { + obj[names[0]] = obj[names[0]] || {}; + obj = obj[names[0]]; + name = names[1]; } + + Object.defineProperty(obj, name, proto); + + var toAsyncName = function (prefix, name) { + return prefix + name.charAt(0).toUpperCase() + name.slice(1); + }; + + obj[toAsyncName('get', name)] = this.getAsync.bind(this); }; /** @@ -3211,22 +3358,27 @@ Property.prototype.get = function () { }; /** - * Should be used to set value of the property + * Should be used to asynchrounously get value of property * - * @method set - * @param {Object} new value of the property + * @method getAsync + * @param {Function} */ -Property.prototype.set = function (value) { - return RequestManager.getInstance().send({ - method: this.setter, - params: [this.formatInput(value)] +Property.prototype.getAsync = function (callback) { + var self = this; + RequestManager.getInstance().sendAsync({ + method: this.getter + }, function (err, result) { + if (err) { + return callback(err); + } + callback(err, self.formatOutput(result)); }); }; module.exports = Property; -},{"./requestmanager":25}],24:[function(require,module,exports){ +},{"./requestmanager":24}],23:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3261,7 +3413,7 @@ QtSyncProvider.prototype.send = function (payload) { module.exports = QtSyncProvider; -},{}],25:[function(require,module,exports){ +},{}],24:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3369,6 +3521,33 @@ RequestManager.prototype.sendAsync = function (data, callback) { }); }; +/** + * Should be called to asynchronously send batch request + * + * @method sendBatch + * @param {Array} batch data + * @param {Function} callback + */ +RequestManager.prototype.sendBatch = function (data, callback) { + if (!this.provider) { + return callback(errors.InvalidProvider()); + } + + var payload = Jsonrpc.getInstance().toBatchPayload(data); + + this.provider.sendAsync(payload, function (err, results) { + if (err) { + return callback(err); + } + + if (!utils.isArray(results)) { + return callback(errors.InvalidResponse(results)); + } + + callback(err, results); + }); +}; + /** * Should be used to set provider of request manager * @@ -3482,7 +3661,7 @@ RequestManager.prototype.poll = function () { module.exports = RequestManager; -},{"../utils/config":7,"../utils/utils":8,"./errors":13,"./jsonrpc":20}],26:[function(require,module,exports){ +},{"../utils/config":5,"../utils/utils":6,"./errors":12,"./jsonrpc":19}],25:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3552,7 +3731,7 @@ module.exports = { }; -},{"./formatters":17,"./method":21}],27:[function(require,module,exports){ +},{"./formatters":16,"./method":20}],26:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3580,7 +3759,20 @@ var Method = require('./method'); /// @returns an array of objects describing web3.eth.filter api methods var eth = function () { var newFilterCall = function (args) { - return typeof args[0] === 'string' ? 'eth_newBlockFilter' : 'eth_newFilter'; + var type = args[0]; + + switch(type) { + case 'latest': + args.pop(); + this.params = 0; + return 'eth_newBlockFilter'; + case 'pending': + args.pop(); + this.params = 0; + return 'eth_newPendingTransactionFilter'; + default: + return 'eth_newFilter'; + } }; var newFilter = new Method({ @@ -3655,7 +3847,7 @@ module.exports = { }; -},{"./method":21}],28:[function(require,module,exports){ +},{"./method":20}],27:[function(require,module,exports){ },{}],"bignumber.js":[function(require,module,exports){ 'use strict'; @@ -3668,7 +3860,6 @@ var web3 = require('./lib/web3'); web3.providers.HttpProvider = require('./lib/web3/httpprovider'); web3.providers.QtSyncProvider = require('./lib/web3/qtsync'); web3.eth.contract = require('./lib/web3/contract'); -web3.abi = require('./lib/solidity/abi'); // dont override global variable if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') { @@ -3678,7 +3869,7 @@ if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') { module.exports = web3; -},{"./lib/solidity/abi":1,"./lib/web3":10,"./lib/web3/contract":11,"./lib/web3/httpprovider":19,"./lib/web3/qtsync":24}]},{},["web3"]) +},{"./lib/web3":8,"./lib/web3/contract":10,"./lib/web3/httpprovider":18,"./lib/web3/qtsync":23}]},{},["web3"]) //# sourceMappingURL=web3-light.js.map \ No newline at end of file diff --git a/dist/web3-light.js.map b/dist/web3-light.js.map index 31e9b5a44..53b78067d 100644 --- a/dist/web3-light.js.map +++ b/dist/web3-light.js.map @@ -2,16 +2,15 @@ "version": 3, "sources": [ "node_modules/browserify/node_modules/browser-pack/_prelude.js", - "lib/solidity/abi.js", "lib/solidity/coder.js", "lib/solidity/formatters.js", "lib/solidity/param.js", - "lib/solidity/utils.js", "lib/utils/browser-xhr.js", "lib/utils/config.js", "lib/utils/utils.js", "lib/version.json", "lib/web3.js", + "lib/web3/batch.js", "lib/web3/contract.js", "lib/web3/db.js", "lib/web3/errors.js", @@ -34,40 +33,39 @@ "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;;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", + "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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;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;AACA;;AC3dA;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;AACA;AACA;AACA;AACA;;ACzKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClHA;;ACAA;AACA;AACA;AACA;AACA;;ACJA;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 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.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/** \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/**\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.4.2\"\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');\nvar Batch = require('./web3/batch');\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;\nweb3.createBatch = function () {\n return new Batch();\n};\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 batch.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar RequestManager = require('./requestmanager');\n\nvar Batch = function () {\n this.requests = [];\n};\n\n/**\n * Should be called to add create new request to batch request\n *\n * @method add\n * @param {Object} jsonrpc requet object\n */\nBatch.prototype.add = function (request) {\n this.requests.push(request);\n};\n\n/**\n * Should be called to execute batch request\n *\n * @method execute\n */\nBatch.prototype.execute = function () {\n var requests = this.requests;\n RequestManager.getInstance().sendBatch(requests, function (err, results) {\n results = results || [];\n requests.map(function (request, index) {\n return results[index] || {};\n }).map(function (result, index) {\n return requests[index].format ? requests[index].format(result.result) : result.result;\n }).forEach(function (result, index) {\n if (requests[index].callback) {\n requests[index].callback(err, result);\n }\n });\n }); \n};\n\nmodule.exports = Batch;\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 utils = require('../utils/utils');\nvar coder = require('../solidity/coder');\nvar SolidityEvent = require('./event');\nvar SolidityFunction = require('./function');\n\n/**\n * Should be called to encode constructor params\n *\n * @method encodeConstructorParams\n * @param {Array} abi\n * @param {Array} constructor params\n */\nvar encodeConstructorParams = function (abi, params) {\n return abi.filter(function (json) {\n return json.type === 'constructor' && json.inputs.length === params.length;\n }).map(function (json) {\n return json.inputs.map(function (input) {\n return input.type;\n });\n }).map(function (types) {\n return coder.encodeParams(types, params);\n })[0] || '';\n};\n\n/**\n * Should be called to add functions to contract object\n *\n * @method addFunctionsToContract\n * @param {Contract} contract\n * @param {Array} abi\n */\nvar addFunctionsToContract = function (contract, abi) {\n abi.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\n/**\n * Should be called to add events to contract object\n *\n * @method addEventsToContract\n * @param {Contract} contract\n * @param {Array} abi\n */\nvar addEventsToContract = function (contract, abi) {\n abi.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 * Should be called to create new ContractFactory\n *\n * @method contract\n * @param {Array} abi\n * @returns {ContractFactory} new contract factory\n */\nvar contract = function (abi) {\n return new ContractFactory(abi);\n};\n\n/**\n * Should be called to create new ContractFactory instance\n *\n * @method ContractFactory\n * @param {Array} abi\n */\nvar ContractFactory = function (abi) {\n this.abi = abi;\n};\n\n/**\n * Should be called to create new contract on a blockchain\n * \n * @method new\n * @param {Any} contract constructor param1 (optional)\n * @param {Any} contract constructor param2 (optional)\n * @param {Object} contract transaction object (required)\n * @param {Function} callback\n * @returns {Contract} returns contract if no callback was passed,\n * otherwise calls callback function (err, contract)\n */\nContractFactory.prototype.new = function () {\n // parse arguments\n var options = {}; // required!\n var callback;\n\n var args = Array.prototype.slice.call(arguments);\n if (utils.isFunction(args[args.length - 1])) {\n callback = args.pop();\n }\n\n var last = args[args.length - 1];\n if (utils.isObject(last) && !utils.isArray(last)) {\n options = args.pop();\n }\n\n // throw an error if there are no options\n\n var bytes = encodeConstructorParams(this.abi, args);\n options.data += bytes;\n\n if (!callback) {\n var address = web3.eth.sendTransaction(options);\n return this.at(address);\n }\n \n var self = this;\n web3.eth.sendTransaction(options, function (err, address) {\n if (err) {\n callback(err);\n }\n self.at(address, callback); \n }); \n};\n\n/**\n * Should be called to get access to existing contract on a blockchain\n *\n * @method at\n * @param {Address} contract address (required)\n * @param {Function} callback {optional)\n * @returns {Contract} returns contract if no callback was passed,\n * otherwise calls callback function (err, contract)\n */\nContractFactory.prototype.at = function (address, callback) {\n // TODO: address is required\n \n if (callback) {\n callback(null, new Contract(this.abi, address));\n } \n return new Contract(this.abi, address);\n};\n\n/**\n * Should be called to create new contract instance\n *\n * @method Contract\n * @param {Array} abi\n * @param {Address} contract address\n */\nvar Contract = function (abi, address) {\n this.address = address;\n addFunctionsToContract(this, abi);\n addEventsToContract(this, abi);\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: '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 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 estimateGas = new Method({\n name: 'estimateGas',\n call: 'eth_estimateGas',\n params: 1,\n inputFormatter: [formatters.inputTransactionFormatter],\n outputFormatter: utils.toDecimal\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 submitWork = new Method({\n name: 'submitWork',\n call: 'eth_submitWork',\n params: 3\n});\n\nvar getWork = new Method({\n name: 'getWork',\n call: 'eth_getWork',\n params: 0\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 estimateGas,\n sendTransaction,\n compileSolidity,\n compileLLL,\n compileSerpent,\n submitWork,\n getWork\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', '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/**\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\nSolidityFunction.prototype.extractCallback = function (args) {\n if (utils.isFunction(args[args.length - 1])) {\n return args.pop(); // modify the args array!\n }\n};\n\n/**\n * Should be used to create payload from arguments\n *\n * @method toPayload\n * @param {Array} solidity function params\n * @param {Object} optional payload options\n */\nSolidityFunction.prototype.toPayload = function (args) {\n var options = {};\n if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) {\n options = args[args.length - 1];\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\nSolidityFunction.prototype.unpackOutput = function (output) {\n if (output === null) {\n return;\n }\n\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 * Calls a contract function.\n *\n * @method call\n * @param {...Object} Contract function arguments\n * @param {function} If the last argument is a function, the contract function\n * call will be asynchronous, and the callback will be passed the\n * error and result.\n * @return {String} output bytes\n */\nSolidityFunction.prototype.call = function () {\n var args = Array.prototype.slice.call(arguments);\n var callback = this.extractCallback(args);\n var payload = this.toPayload(args);\n\n if (!callback) {\n var output = web3.eth.call(payload);\n return this.unpackOutput(output);\n } \n \n var self = this;\n web3.eth.call(payload, function (error, output) {\n callback(error, self.unpackOutput(output));\n });\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 args = Array.prototype.slice.call(arguments);\n var callback = this.extractCallback(args);\n var payload = this.toPayload(args);\n\n if (!callback) {\n web3.eth.sendTransaction(payload);\n return;\n }\n\n web3.eth.sendTransaction(payload, callback);\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 get rpc requests from solidity function\n *\n * @method request\n * @returns {Object}\n */\nSolidityFunction.prototype.request = function () {\n var args = Array.prototype.slice.call(arguments);\n var callback = this.extractCallback(args);\n var payload = this.toPayload(args);\n var format = this.unpackOutput.bind(this);\n \n return {\n callback: callback,\n payload: payload, \n format: format\n };\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.request = this.request.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\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/**\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};\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.request = this.request.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 be called to create pure JSONRPC request which can be used in batch request\n *\n * @method request\n * @param {...} params\n * @return {Object} jsonrpc request\n */\nMethod.prototype.request = function () {\n var payload = this.toPayload(Array.prototype.slice.call(arguments));\n payload.format = this.formatOutput.bind(this);\n return payload;\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(err, 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", - "/*\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 property.js\n * @author Fabian Vogelsteller \n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar RequestManager = require('./requestmanager');\n\nvar Property = function (options) {\n this.name = options.name;\n this.getter = options.getter;\n this.setter = options.setter;\n this.outputFormatter = options.outputFormatter;\n this.inputFormatter = options.inputFormatter;\n};\n\n/**\n * Should be called to format input args of method\n * \n * @method formatInput\n * @param {Array}\n * @return {Array}\n */\nProperty.prototype.formatInput = function (arg) {\n return this.inputFormatter ? this.inputFormatter(arg) : arg;\n};\n\n/**\n * Should be called to format output(result) of method\n *\n * @method formatOutput\n * @param {Object}\n * @return {Object}\n */\nProperty.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 */\nProperty.prototype.attachToObject = function (obj) {\n var proto = {\n get: this.get.bind(this),\n set: this.set.bind(this)\n };\n\n var name = this.name.split('.');\n if (name.length > 1) {\n obj[name[0]] = obj[name[0]] || {};\n Object.defineProperty(obj[name[0]], name[1], proto); \n } else {\n Object.defineProperty(obj, name[0], proto);\n }\n};\n\n/**\n * Should be used to get value of the property\n *\n * @method get\n * @return {Object} value of the property\n */\nProperty.prototype.get = function () {\n return this.formatOutput(RequestManager.getInstance().send({\n method: this.getter\n }));\n};\n\n/**\n * Should be used to set value of the property\n *\n * @method set\n * @param {Object} new value of the property\n */\nProperty.prototype.set = function (value) {\n return RequestManager.getInstance().send({\n method: this.setter,\n params: [this.formatInput(value)]\n });\n};\n\nmodule.exports = Property;\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 property.js\n * @author Fabian Vogelsteller \n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar RequestManager = require('./requestmanager');\n\nvar Property = function (options) {\n this.name = options.name;\n this.getter = options.getter;\n this.setter = options.setter;\n this.outputFormatter = options.outputFormatter;\n this.inputFormatter = options.inputFormatter;\n};\n\n/**\n * Should be called to format input args of method\n * \n * @method formatInput\n * @param {Array}\n * @return {Array}\n */\nProperty.prototype.formatInput = function (arg) {\n return this.inputFormatter ? this.inputFormatter(arg) : arg;\n};\n\n/**\n * Should be called to format output(result) of method\n *\n * @method formatOutput\n * @param {Object}\n * @return {Object}\n */\nProperty.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 */\nProperty.prototype.attachToObject = function (obj) {\n var proto = {\n get: this.get.bind(this),\n };\n\n var names = this.name.split('.');\n var name = names[0];\n if (names.length > 1) {\n obj[names[0]] = obj[names[0]] || {};\n obj = obj[names[0]];\n name = names[1];\n }\n \n Object.defineProperty(obj, name, proto);\n\n var toAsyncName = function (prefix, name) {\n return prefix + name.charAt(0).toUpperCase() + name.slice(1);\n };\n\n obj[toAsyncName('get', name)] = this.getAsync.bind(this);\n};\n\n/**\n * Should be used to get value of the property\n *\n * @method get\n * @return {Object} value of the property\n */\nProperty.prototype.get = function () {\n return this.formatOutput(RequestManager.getInstance().send({\n method: this.getter\n }));\n};\n\n/**\n * Should be used to asynchrounously get value of property\n *\n * @method getAsync\n * @param {Function}\n */\nProperty.prototype.getAsync = function (callback) {\n var self = this;\n RequestManager.getInstance().sendAsync({\n method: this.getter\n }, function (err, result) {\n if (err) {\n return callback(err);\n }\n callback(err, self.formatOutput(result));\n });\n};\n\nmodule.exports = Property;\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 qtsync.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\nvar QtSyncProvider = function () {\n};\n\nQtSyncProvider.prototype.send = function (payload) {\n var result = navigator.qt.callMethod(JSON.stringify(payload));\n return JSON.parse(result);\n};\n\nmodule.exports = QtSyncProvider;\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 requestmanager.js\n * @author Jeffrey Wilcke \n * @author Marek Kotewicz \n * @author Marian Oancea \n * @author Fabian Vogelsteller \n * @author Gav Wood \n * @date 2014\n */\n\nvar Jsonrpc = require('./jsonrpc');\nvar utils = require('../utils/utils');\nvar c = require('../utils/config');\nvar errors = require('./errors');\n\n/**\n * It's responsible for passing messages to providers\n * It's also responsible for polling the ethereum node for incoming messages\n * Default poll timeout is 1 second\n * Singleton\n */\nvar RequestManager = function (provider) {\n // singleton pattern\n if (arguments.callee._singletonInstance) {\n return arguments.callee._singletonInstance;\n }\n arguments.callee._singletonInstance = this;\n\n this.provider = provider;\n this.polls = [];\n this.timeout = null;\n this.poll();\n};\n\n/**\n * @return {RequestManager} singleton\n */\nRequestManager.getInstance = function () {\n var instance = new RequestManager();\n return instance;\n};\n\n/**\n * Should be used to synchronously send request\n *\n * @method send\n * @param {Object} data\n * @return {Object}\n */\nRequestManager.prototype.send = function (data) {\n if (!this.provider) {\n console.error(errors.InvalidProvider());\n return null;\n }\n\n var payload = Jsonrpc.getInstance().toPayload(data.method, data.params);\n var result = this.provider.send(payload);\n\n if (!Jsonrpc.getInstance().isValidResponse(result)) {\n throw errors.InvalidResponse(result);\n }\n\n return result.result;\n};\n\n/**\n * Should be used to asynchronously send request\n *\n * @method sendAsync\n * @param {Object} data\n * @param {Function} callback\n */\nRequestManager.prototype.sendAsync = function (data, callback) {\n if (!this.provider) {\n return callback(errors.InvalidProvider());\n }\n\n var payload = Jsonrpc.getInstance().toPayload(data.method, data.params);\n this.provider.sendAsync(payload, function (err, result) {\n if (err) {\n return callback(err);\n }\n \n if (!Jsonrpc.getInstance().isValidResponse(result)) {\n return callback(errors.InvalidResponse(result));\n }\n\n callback(null, result.result);\n });\n};\n\n/**\n * Should be used to set provider of request manager\n *\n * @method setProvider\n * @param {Object}\n */\nRequestManager.prototype.setProvider = function (p) {\n this.provider = p;\n};\n\n/*jshint maxparams:4 */\n\n/**\n * Should be used to start polling\n *\n * @method startPolling\n * @param {Object} data\n * @param {Number} pollId\n * @param {Function} callback\n * @param {Function} uninstall\n *\n * @todo cleanup number of params\n */\nRequestManager.prototype.startPolling = function (data, pollId, callback, uninstall) {\n this.polls.push({data: data, id: pollId, callback: callback, uninstall: uninstall});\n};\n/*jshint maxparams:3 */\n\n/**\n * Should be used to stop polling for filter with given id\n *\n * @method stopPolling\n * @param {Number} pollId\n */\nRequestManager.prototype.stopPolling = function (pollId) {\n for (var i = this.polls.length; i--;) {\n var poll = this.polls[i];\n if (poll.id === pollId) {\n this.polls.splice(i, 1);\n }\n }\n};\n\n/**\n * Should be called to reset polling mechanism of request manager\n *\n * @method reset\n */\nRequestManager.prototype.reset = function () {\n this.polls.forEach(function (poll) {\n poll.uninstall(poll.id); \n });\n this.polls = [];\n\n if (this.timeout) {\n clearTimeout(this.timeout);\n this.timeout = null;\n }\n this.poll();\n};\n\n/**\n * Should be called to poll for changes on filter with given id\n *\n * @method poll\n */\nRequestManager.prototype.poll = function () {\n this.timeout = setTimeout(this.poll.bind(this), c.ETH_POLLING_TIMEOUT);\n\n if (!this.polls.length) {\n return;\n }\n\n if (!this.provider) {\n console.error(errors.InvalidProvider());\n return;\n }\n\n var payload = Jsonrpc.getInstance().toBatchPayload(this.polls.map(function (data) {\n return data.data;\n }));\n\n var self = this;\n this.provider.sendAsync(payload, function (error, results) {\n // TODO: console log?\n if (error) {\n return;\n }\n \n if (!utils.isArray(results)) {\n throw errors.InvalidResponse(results);\n }\n\n results.map(function (result, index) {\n result.callback = self.polls[index].callback;\n return result;\n }).filter(function (result) {\n var valid = Jsonrpc.getInstance().isValidResponse(result);\n if (!valid) {\n result.callback(errors.InvalidResponse(result));\n }\n return valid;\n }).filter(function (result) {\n return utils.isArray(result.result) && result.result.length > 0;\n }).forEach(function (result) {\n result.callback(null, result.result);\n });\n });\n};\n\nmodule.exports = RequestManager;\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 requestmanager.js\n * @author Jeffrey Wilcke \n * @author Marek Kotewicz \n * @author Marian Oancea \n * @author Fabian Vogelsteller \n * @author Gav Wood \n * @date 2014\n */\n\nvar Jsonrpc = require('./jsonrpc');\nvar utils = require('../utils/utils');\nvar c = require('../utils/config');\nvar errors = require('./errors');\n\n/**\n * It's responsible for passing messages to providers\n * It's also responsible for polling the ethereum node for incoming messages\n * Default poll timeout is 1 second\n * Singleton\n */\nvar RequestManager = function (provider) {\n // singleton pattern\n if (arguments.callee._singletonInstance) {\n return arguments.callee._singletonInstance;\n }\n arguments.callee._singletonInstance = this;\n\n this.provider = provider;\n this.polls = [];\n this.timeout = null;\n this.poll();\n};\n\n/**\n * @return {RequestManager} singleton\n */\nRequestManager.getInstance = function () {\n var instance = new RequestManager();\n return instance;\n};\n\n/**\n * Should be used to synchronously send request\n *\n * @method send\n * @param {Object} data\n * @return {Object}\n */\nRequestManager.prototype.send = function (data) {\n if (!this.provider) {\n console.error(errors.InvalidProvider());\n return null;\n }\n\n var payload = Jsonrpc.getInstance().toPayload(data.method, data.params);\n var result = this.provider.send(payload);\n\n if (!Jsonrpc.getInstance().isValidResponse(result)) {\n throw errors.InvalidResponse(result);\n }\n\n return result.result;\n};\n\n/**\n * Should be used to asynchronously send request\n *\n * @method sendAsync\n * @param {Object} data\n * @param {Function} callback\n */\nRequestManager.prototype.sendAsync = function (data, callback) {\n if (!this.provider) {\n return callback(errors.InvalidProvider());\n }\n\n var payload = Jsonrpc.getInstance().toPayload(data.method, data.params);\n this.provider.sendAsync(payload, function (err, result) {\n if (err) {\n return callback(err);\n }\n \n if (!Jsonrpc.getInstance().isValidResponse(result)) {\n return callback(errors.InvalidResponse(result));\n }\n\n callback(null, result.result);\n });\n};\n\n/**\n * Should be called to asynchronously send batch request\n *\n * @method sendBatch\n * @param {Array} batch data\n * @param {Function} callback\n */\nRequestManager.prototype.sendBatch = function (data, callback) {\n if (!this.provider) {\n return callback(errors.InvalidProvider());\n }\n\n var payload = Jsonrpc.getInstance().toBatchPayload(data);\n\n this.provider.sendAsync(payload, function (err, results) {\n if (err) {\n return callback(err);\n }\n\n if (!utils.isArray(results)) {\n return callback(errors.InvalidResponse(results));\n }\n\n callback(err, results);\n }); \n};\n\n/**\n * Should be used to set provider of request manager\n *\n * @method setProvider\n * @param {Object}\n */\nRequestManager.prototype.setProvider = function (p) {\n this.provider = p;\n};\n\n/*jshint maxparams:4 */\n\n/**\n * Should be used to start polling\n *\n * @method startPolling\n * @param {Object} data\n * @param {Number} pollId\n * @param {Function} callback\n * @param {Function} uninstall\n *\n * @todo cleanup number of params\n */\nRequestManager.prototype.startPolling = function (data, pollId, callback, uninstall) {\n this.polls.push({data: data, id: pollId, callback: callback, uninstall: uninstall});\n};\n/*jshint maxparams:3 */\n\n/**\n * Should be used to stop polling for filter with given id\n *\n * @method stopPolling\n * @param {Number} pollId\n */\nRequestManager.prototype.stopPolling = function (pollId) {\n for (var i = this.polls.length; i--;) {\n var poll = this.polls[i];\n if (poll.id === pollId) {\n this.polls.splice(i, 1);\n }\n }\n};\n\n/**\n * Should be called to reset polling mechanism of request manager\n *\n * @method reset\n */\nRequestManager.prototype.reset = function () {\n this.polls.forEach(function (poll) {\n poll.uninstall(poll.id); \n });\n this.polls = [];\n\n if (this.timeout) {\n clearTimeout(this.timeout);\n this.timeout = null;\n }\n this.poll();\n};\n\n/**\n * Should be called to poll for changes on filter with given id\n *\n * @method poll\n */\nRequestManager.prototype.poll = function () {\n this.timeout = setTimeout(this.poll.bind(this), c.ETH_POLLING_TIMEOUT);\n\n if (!this.polls.length) {\n return;\n }\n\n if (!this.provider) {\n console.error(errors.InvalidProvider());\n return;\n }\n\n var payload = Jsonrpc.getInstance().toBatchPayload(this.polls.map(function (data) {\n return data.data;\n }));\n\n var self = this;\n this.provider.sendAsync(payload, function (error, results) {\n // TODO: console log?\n if (error) {\n return;\n }\n \n if (!utils.isArray(results)) {\n throw errors.InvalidResponse(results);\n }\n\n results.map(function (result, index) {\n result.callback = self.polls[index].callback;\n return result;\n }).filter(function (result) {\n var valid = Jsonrpc.getInstance().isValidResponse(result);\n if (!valid) {\n result.callback(errors.InvalidResponse(result));\n }\n return valid;\n }).filter(function (result) {\n return utils.isArray(result.result) && result.result.length > 0;\n }).forEach(function (result) {\n result.callback(null, result.result);\n });\n });\n};\n\nmodule.exports = RequestManager;\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 shh.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar Method = require('./method');\nvar formatters = require('./formatters');\n\nvar post = new Method({\n name: 'post', \n call: 'shh_post', \n params: 1,\n inputFormatter: [formatters.inputPostFormatter]\n});\n\nvar newIdentity = new Method({\n name: 'newIdentity',\n call: 'shh_newIdentity',\n params: 0\n});\n\nvar hasIdentity = new Method({\n name: 'hasIdentity',\n call: 'shh_hasIdentity',\n params: 1\n});\n\nvar newGroup = new Method({\n name: 'newGroup',\n call: 'shh_newGroup',\n params: 0\n});\n\nvar addToGroup = new Method({\n name: 'addToGroup',\n call: 'shh_addToGroup',\n params: 0\n});\n\nvar methods = [\n post,\n newIdentity,\n hasIdentity,\n newGroup,\n addToGroup\n];\n\nmodule.exports = {\n methods: methods\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 watches.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar Method = require('./method');\n\n/// @returns an array of objects describing web3.eth.filter api methods\nvar eth = function () {\n var newFilterCall = function (args) {\n return typeof args[0] === 'string' ? 'eth_newBlockFilter' : 'eth_newFilter';\n };\n\n var newFilter = new Method({\n name: 'newFilter',\n call: newFilterCall,\n params: 1\n });\n\n var uninstallFilter = new Method({\n name: 'uninstallFilter',\n call: 'eth_uninstallFilter',\n params: 1\n });\n\n var getLogs = new Method({\n name: 'getLogs',\n call: 'eth_getFilterLogs',\n params: 1\n });\n\n var poll = new Method({\n name: 'poll',\n call: 'eth_getFilterChanges',\n params: 1\n });\n\n return [\n newFilter,\n uninstallFilter,\n getLogs,\n poll\n ];\n};\n\n/// @returns an array of objects describing web3.shh.watch api methods\nvar shh = function () {\n var newFilter = new Method({\n name: 'newFilter',\n call: 'shh_newFilter',\n params: 1\n });\n\n var uninstallFilter = new Method({\n name: 'uninstallFilter',\n call: 'shh_uninstallFilter',\n params: 1\n });\n\n var getLogs = new Method({\n name: 'getLogs',\n call: 'shh_getMessages',\n params: 1\n });\n\n var poll = new Method({\n name: 'poll',\n call: 'shh_getFilterChanges',\n params: 1\n });\n\n return [\n newFilter,\n uninstallFilter,\n getLogs,\n poll\n ];\n};\n\nmodule.exports = {\n eth: eth,\n shh: shh\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 watches.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar Method = require('./method');\n\n/// @returns an array of objects describing web3.eth.filter api methods\nvar eth = function () {\n var newFilterCall = function (args) {\n var type = args[0];\n\n switch(type) {\n case 'latest':\n args.pop();\n this.params = 0;\n return 'eth_newBlockFilter';\n case 'pending':\n args.pop();\n this.params = 0;\n return 'eth_newPendingTransactionFilter';\n default:\n return 'eth_newFilter';\n }\n };\n\n var newFilter = new Method({\n name: 'newFilter',\n call: newFilterCall,\n params: 1\n });\n\n var uninstallFilter = new Method({\n name: 'uninstallFilter',\n call: 'eth_uninstallFilter',\n params: 1\n });\n\n var getLogs = new Method({\n name: 'getLogs',\n call: 'eth_getFilterLogs',\n params: 1\n });\n\n var poll = new Method({\n name: 'poll',\n call: 'eth_getFilterChanges',\n params: 1\n });\n\n return [\n newFilter,\n uninstallFilter,\n getLogs,\n poll\n ];\n};\n\n/// @returns an array of objects describing web3.shh.watch api methods\nvar shh = function () {\n var newFilter = new Method({\n name: 'newFilter',\n call: 'shh_newFilter',\n params: 1\n });\n\n var uninstallFilter = new Method({\n name: 'uninstallFilter',\n call: 'shh_uninstallFilter',\n params: 1\n });\n\n var getLogs = new Method({\n name: 'getLogs',\n call: 'shh_getMessages',\n params: 1\n });\n\n var poll = new Method({\n name: 'poll',\n call: 'shh_getFilterChanges',\n params: 1\n });\n\n return [\n newFilter,\n uninstallFilter,\n getLogs,\n poll\n ];\n};\n\nmodule.exports = {\n eth: eth,\n shh: shh\n};\n\n", null, "'use strict';\n\nmodule.exports = BigNumber; // jshint ignore:line\n\n", - "var web3 = require('./lib/web3');\nweb3.providers.HttpProvider = require('./lib/web3/httpprovider');\nweb3.providers.QtSyncProvider = require('./lib/web3/qtsync');\nweb3.eth.contract = require('./lib/web3/contract');\nweb3.abi = require('./lib/solidity/abi');\n\n// dont override global variable\nif (typeof window !== 'undefined' && typeof window.web3 === 'undefined') {\n window.web3 = web3;\n}\n\nmodule.exports = web3;\n\n" + "var web3 = require('./lib/web3');\nweb3.providers.HttpProvider = require('./lib/web3/httpprovider');\nweb3.providers.QtSyncProvider = require('./lib/web3/qtsync');\nweb3.eth.contract = require('./lib/web3/contract');\n\n// dont override global variable\nif (typeof window !== 'undefined' && typeof window.web3 === 'undefined') {\n window.web3 = web3;\n}\n\nmodule.exports = web3;\n\n" ] } \ No newline at end of file diff --git a/dist/web3-light.min.js b/dist/web3-light.min.js index 4c0fd2930..22527f18e 100644 --- a/dist/web3-light.min.js +++ b/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={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 +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;ai;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":6,"./formatters":2,"./param":3,"bignumber.js":"bignumber.js"}],2:[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)},p=function(t){return s(new r(t).times(new r(2).pow(128)))},f=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 f(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))},y=function(t){return h(t).dividedBy(new r(2).pow(128))},g=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:p,formatOutputInt:m,formatOutputUInt:h,formatOutputReal:d,formatOutputUReal:y,formatOutputBool:g,formatOutputBytes:v,formatOutputDynamicBytes:b,formatOutputAddress:w}},{"../utils/config":5,"../utils/utils":6,"./param":3,"bignumber.js":"bignumber.js"}],3:[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":6}],4:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],5:[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"}],6:[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[t.length-1]),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.unpackOutput=function(t){if(null!==t){t=t.length>=2?t.slice(2):t;var e=o.decodeParams(this._outputTypes,t);return 1===e.length?e[0]:e}},a.prototype.call=function(){var t=Array.prototype.slice.call(arguments),e=this.extractCallback(t),n=this.toPayload(t);if(!e){var o=r.eth.call(n);return this.unpackOutput(o)}var i=this;r.eth.call(n,function(t,n){e(t,i.unpackOutput(n))})},a.prototype.sendTransaction=function(){var t=Array.prototype.slice.call(arguments),e=this.extractCallback(t),n=this.toPayload(t);return e?void r.eth.sendTransaction(n,e):void r.eth.sendTransaction(n)},a.prototype.displayName=function(){return i.extractDisplayName(this._name)},a.prototype.typeName=function(){return i.extractTypeName(this._name)},a.prototype.request=function(){var t=Array.prototype.slice.call(arguments),e=this.extractCallback(t),n=this.toPayload(t),r=this.unpackOutput.bind(this);return{callback:e,payload:n,format:r}},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.request=this.request.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":1,"../utils/utils":6,"../web3":8}],18:[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":12,xmlhttprequest:4}],19:[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},{}],20:[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():void 0},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.request=this.request.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.request=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));return t.format=this.formatOutput.bind(this),t},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(n,e.formatOutput(r))})}return this.formatOutput(r.getInstance().send(t))},e.exports=a},{"../utils/utils":6,"./errors":12,"./requestmanager":24}],21:[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":6,"./property":22}],22:[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)},n=this.name.split("."),r=n[0];n.length>1&&(t[n[0]]=t[n[0]]||{},t=t[n[0]],r=n[1]),Object.defineProperty(t,r,e);var o=function(t,e){return t+e.charAt(0).toUpperCase()+e.slice(1)};t[o("get",r)]=this.getAsync.bind(this)},o.prototype.get=function(){return this.formatOutput(r.getInstance().send({method:this.getter}))},o.prototype.getAsync=function(t){var e=this;r.getInstance().sendAsync({method:this.getter},function(n,r){return n?t(n):void t(n,e.formatOutput(r))})},e.exports=o},{"./requestmanager":24}],23:[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},{}],24:[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.sendBatch=function(t,e){if(!this.provider)return e(a.InvalidProvider());var n=r.getInstance().toBatchPayload(t);this.provider.sendAsync(n,function(t,n){return t?e(t):o.isArray(n)?void e(t,n):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":5,"../utils/utils":6,"./errors":12,"./jsonrpc":19}],25:[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":16,"./method":20}],26:[function(t,e,n){var r=t("./method"),o=function(){var t=function(t){var e=t[0];switch(e){case"latest":return t.pop(),this.params=0,"eth_newBlockFilter";case"pending":return t.pop(),this.params=0,"eth_newPendingTransactionFilter";default:return"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":20}],27:[function(t,e,n){},{}],"bignumber.js":[function(t,e,n){"use strict";e.exports=BigNumber},{}],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"),"undefined"!=typeof window&&"undefined"==typeof window.web3&&(window.web3=r),e.exports=r},{"./lib/web3":8,"./lib/web3/contract":10,"./lib/web3/httpprovider":18,"./lib/web3/qtsync":23}]},{},["web3"]); \ No newline at end of file diff --git a/dist/web3.js b/dist/web3.js index ec66a38d8..2745ab36f 100644 --- a/dist/web3.js +++ b/dist/web3.js @@ -15,52 +15,6 @@ require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof requ You should have received a copy of the GNU Lesser General Public License along with ethereum.js. If not, see . */ -/** - * @file abi.js - * @author Marek Kotewicz - * @author Gav Wood - * @date 2014 - */ - -var coder = require('./coder'); -var utils = require('./utils'); - -var formatConstructorParams = function (abi, params) { - 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 coder.encodeParams(constructor.inputs.map(function (input) { - return input.type; - }), params); -}; - -module.exports = { - formatConstructorParams: formatConstructorParams -}; - - -},{"./coder":2,"./utils":5}],2:[function(require,module,exports){ -/* - This file is part of ethereum.js. - - ethereum.js is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - ethereum.js 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with ethereum.js. If not, see . -*/ /** * @file coder.js * @author Marek Kotewicz @@ -328,7 +282,7 @@ var coder = new SolidityCoder([ module.exports = coder; -},{"../utils/utils":8,"./formatters":3,"./param":4,"bignumber.js":"bignumber.js"}],3:[function(require,module,exports){ +},{"../utils/utils":6,"./formatters":2,"./param":3,"bignumber.js":"bignumber.js"}],2:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -548,7 +502,7 @@ module.exports = { }; -},{"../utils/config":7,"../utils/utils":8,"./param":4,"bignumber.js":"bignumber.js"}],4:[function(require,module,exports){ +},{"../utils/config":5,"../utils/utils":6,"./param":3,"bignumber.js":"bignumber.js"}],3:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -760,54 +714,7 @@ SolidityParam.decodeArray = function (bytes, index) { module.exports = SolidityParam; -},{"../utils/utils":8}],5:[function(require,module,exports){ -/* - This file is part of ethereum.js. - - ethereum.js is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - ethereum.js 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with ethereum.js. If not, see . -*/ -/** - * @file utils.js - * @author Marek Kotewicz - * @date 2015 - */ - -/** - * Returns the contstructor with matching number of arguments - * - * @method getConstructor - * @param {Array} abi - * @param {Number} numberOfArgs - * @returns {Object} constructor function abi - */ -var getConstructor = function (abi, numberOfArgs) { - return abi.filter(function (f) { - return f.type === 'constructor' && f.inputs.length === numberOfArgs; - })[0]; -}; - -//var getSupremeType = function (type) { - //return type.substr(0, type.indexOf('[')) + ']'; -//}; - - -module.exports = { - getConstructor: getConstructor -}; - - -},{}],6:[function(require,module,exports){ +},{"../utils/utils":6}],4:[function(require,module,exports){ 'use strict'; // go env doesn't have and need XMLHttpRequest @@ -818,7 +725,7 @@ if (typeof XMLHttpRequest === 'undefined') { } -},{}],7:[function(require,module,exports){ +},{}],5:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -890,7 +797,7 @@ module.exports = { }; -},{"bignumber.js":"bignumber.js"}],8:[function(require,module,exports){ +},{"bignumber.js":"bignumber.js"}],6:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1256,6 +1163,7 @@ var toAddress = function (address) { return '0x' + padLeft(toHex(address).substr(2), 40); }; + /** * Returns true if object is BigNumber, otherwise false * @@ -1366,12 +1274,12 @@ module.exports = { }; -},{"bignumber.js":"bignumber.js"}],9:[function(require,module,exports){ +},{"bignumber.js":"bignumber.js"}],7:[function(require,module,exports){ module.exports={ - "version": "0.3.6" + "version": "0.4.2" } -},{}],10:[function(require,module,exports){ +},{}],8:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1411,6 +1319,7 @@ var RequestManager = require('./web3/requestmanager'); var c = require('./utils/config'); var Method = require('./web3/method'); var Property = require('./web3/property'); +var Batch = require('./web3/batch'); var web3Methods = [ new Method({ @@ -1503,6 +1412,9 @@ web3.toBigNumber = utils.toBigNumber; web3.toWei = utils.toWei; web3.fromWei = utils.fromWei; web3.isAddress = utils.isAddress; +web3.createBatch = function () { + return new Batch(); +}; // ADD defaultblock Object.defineProperty(web3.eth, 'defaultBlock', { @@ -1538,7 +1450,70 @@ setupMethods(web3.shh, shh.methods); module.exports = web3; -},{"./utils/config":7,"./utils/utils":8,"./version.json":9,"./web3/db":12,"./web3/eth":14,"./web3/filter":16,"./web3/formatters":17,"./web3/method":21,"./web3/net":22,"./web3/property":23,"./web3/requestmanager":25,"./web3/shh":26,"./web3/watches":27}],11:[function(require,module,exports){ +},{"./utils/config":5,"./utils/utils":6,"./version.json":7,"./web3/batch":9,"./web3/db":11,"./web3/eth":13,"./web3/filter":15,"./web3/formatters":16,"./web3/method":20,"./web3/net":21,"./web3/property":22,"./web3/requestmanager":24,"./web3/shh":25,"./web3/watches":26}],9:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** + * @file batch.js + * @author Marek Kotewicz + * @date 2015 + */ + +var RequestManager = require('./requestmanager'); + +var Batch = function () { + this.requests = []; +}; + +/** + * Should be called to add create new request to batch request + * + * @method add + * @param {Object} jsonrpc requet object + */ +Batch.prototype.add = function (request) { + this.requests.push(request); +}; + +/** + * Should be called to execute batch request + * + * @method execute + */ +Batch.prototype.execute = function () { + var requests = this.requests; + RequestManager.getInstance().sendBatch(requests, function (err, results) { + results = results || []; + requests.map(function (request, index) { + return results[index] || {}; + }).map(function (result, index) { + return requests[index].format ? requests[index].format(result.result) : result.result; + }).forEach(function (result, index) { + if (requests[index].callback) { + requests[index].callback(err, result); + } + }); + }); +}; + +module.exports = Batch; + + +},{"./requestmanager":24}],10:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1562,13 +1537,39 @@ module.exports = web3; */ var web3 = require('../web3'); -var solAbi = require('../solidity/abi'); var utils = require('../utils/utils'); +var coder = require('../solidity/coder'); var SolidityEvent = require('./event'); var SolidityFunction = require('./function'); -var addFunctionsToContract = function (contract, desc) { - desc.filter(function (json) { +/** + * Should be called to encode constructor params + * + * @method encodeConstructorParams + * @param {Array} abi + * @param {Array} constructor params + */ +var encodeConstructorParams = function (abi, params) { + return abi.filter(function (json) { + return json.type === 'constructor' && json.inputs.length === params.length; + }).map(function (json) { + return json.inputs.map(function (input) { + return input.type; + }); + }).map(function (types) { + return coder.encodeParams(types, params); + })[0] || ''; +}; + +/** + * Should be called to add functions to contract object + * + * @method addFunctionsToContract + * @param {Contract} contract + * @param {Array} abi + */ +var addFunctionsToContract = function (contract, abi) { + abi.filter(function (json) { return json.type === 'function'; }).map(function (json) { return new SolidityFunction(json, contract.address); @@ -1577,8 +1578,15 @@ var addFunctionsToContract = function (contract, desc) { }); }; -var addEventsToContract = function (contract, desc) { - desc.filter(function (json) { +/** + * Should be called to add events to contract object + * + * @method addEventsToContract + * @param {Contract} contract + * @param {Array} abi + */ +var addEventsToContract = function (contract, abi) { + abi.filter(function (json) { return json.type === 'event'; }).map(function (json) { return new SolidityEvent(json, contract.address); @@ -1588,65 +1596,106 @@ var addEventsToContract = function (contract, desc) { }; /** - * This method should be called when we want to call / transact some solidity method from javascript - * it returns an object which has same methods available as solidity contract description - * usage example: - * - * var abi = [{ - * name: 'myMethod', - * inputs: [{ name: 'a', type: 'string' }], - * outputs: [{name: 'd', type: 'string' }] - * }]; // contract abi - * - * var MyContract = web3.eth.contract(abi); // creation of contract prototype + * Should be called to create new ContractFactory * - * var contractInstance = new MyContract('0x0123123121'); - * - * contractInstance.myMethod('this is test string param for call'); // myMethod call (implicit, default) - * contractInstance.call().myMethod('this is test string param for call'); // myMethod call (explicit) - * contractInstance.sendTransaction().myMethod('this is test string param for transact'); // myMethod sendTransaction - * - * @param abi - abi json description of the contract, which is being created - * @returns contract object + * @method contract + * @param {Array} abi + * @returns {ContractFactory} new contract factory */ var contract = function (abi) { + return new ContractFactory(abi); +}; - // return prototype - return Contract.bind(null, abi); +/** + * Should be called to create new ContractFactory instance + * + * @method ContractFactory + * @param {Array} abi + */ +var ContractFactory = function (abi) { + this.abi = abi; }; -var Contract = function (abi, options) { +/** + * Should be called to create new contract on a blockchain + * + * @method new + * @param {Any} contract constructor param1 (optional) + * @param {Any} contract constructor param2 (optional) + * @param {Object} contract transaction object (required) + * @param {Function} callback + * @returns {Contract} returns contract if no callback was passed, + * otherwise calls callback function (err, contract) + */ +ContractFactory.prototype.new = function () { + // parse arguments + var options = {}; // required! + var callback; - this.address = ''; - if (utils.isAddress(options)) { - this.address = options; - } else { // is an object! - // TODO, parse the rest of the args - options = options || {}; - var args = Array.prototype.slice.call(arguments, 2); - var bytes = solAbi.formatConstructorParams(abi, args); - options.data += bytes; - this.address = web3.eth.sendTransaction(options); + var args = Array.prototype.slice.call(arguments); + if (utils.isFunction(args[args.length - 1])) { + callback = args.pop(); } - addFunctionsToContract(this, abi); - addEventsToContract(this, abi); + var last = args[args.length - 1]; + if (utils.isObject(last) && !utils.isArray(last)) { + options = args.pop(); + } + + // throw an error if there are no options + + var bytes = encodeConstructorParams(this.abi, args); + options.data += bytes; + + if (!callback) { + var address = web3.eth.sendTransaction(options); + return this.at(address); + } + + var self = this; + web3.eth.sendTransaction(options, function (err, address) { + if (err) { + callback(err); + } + self.at(address, callback); + }); }; -Contract.prototype.call = function () { - console.error('contract.call is deprecated'); - return this; +/** + * Should be called to get access to existing contract on a blockchain + * + * @method at + * @param {Address} contract address (required) + * @param {Function} callback {optional) + * @returns {Contract} returns contract if no callback was passed, + * otherwise calls callback function (err, contract) + */ +ContractFactory.prototype.at = function (address, callback) { + // TODO: address is required + + if (callback) { + callback(null, new Contract(this.abi, address)); + } + return new Contract(this.abi, address); }; -Contract.prototype.sendTransaction = function () { - console.error('contract.sendTransact is deprecated'); - return this; +/** + * Should be called to create new contract instance + * + * @method Contract + * @param {Array} abi + * @param {Address} contract address + */ +var Contract = function (abi, address) { + this.address = address; + addFunctionsToContract(this, abi); + addEventsToContract(this, abi); }; module.exports = contract; -},{"../solidity/abi":1,"../utils/utils":8,"../web3":10,"./event":15,"./function":18}],12:[function(require,module,exports){ +},{"../solidity/coder":1,"../utils/utils":6,"../web3":8,"./event":14,"./function":17}],11:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1704,7 +1753,7 @@ module.exports = { methods: methods }; -},{"./method":21}],13:[function(require,module,exports){ +},{"./method":20}],12:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1744,7 +1793,7 @@ module.exports = { }; -},{}],14:[function(require,module,exports){ +},{}],13:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1921,6 +1970,14 @@ var call = new Method({ inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter] }); +var estimateGas = new Method({ + name: 'estimateGas', + call: 'eth_estimateGas', + params: 1, + inputFormatter: [formatters.inputTransactionFormatter], + outputFormatter: utils.toDecimal +}); + var compileSolidity = new Method({ name: 'compile.solidity', call: 'eth_compileSolidity', @@ -1939,6 +1996,18 @@ var compileSerpent = new Method({ params: 1 }); +var submitWork = new Method({ + name: 'submitWork', + call: 'eth_submitWork', + params: 3 +}); + +var getWork = new Method({ + name: 'getWork', + call: 'eth_getWork', + params: 0 +}); + var methods = [ getBalance, getStorageAt, @@ -1952,10 +2021,13 @@ var methods = [ getTransactionFromBlock, getTransactionCount, call, + estimateGas, sendTransaction, compileSolidity, compileLLL, compileSerpent, + submitWork, + getWork ]; /// @returns an array of objects describing web3.eth api properties @@ -1998,7 +2070,7 @@ module.exports = { }; -},{"../utils/utils":8,"./formatters":17,"./method":21,"./property":23}],15:[function(require,module,exports){ +},{"../utils/utils":6,"./formatters":16,"./method":20,"./property":22}],14:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2194,7 +2266,7 @@ SolidityEvent.prototype.attachToContract = function (contract) { module.exports = SolidityEvent; -},{"../solidity/coder":2,"../utils/utils":8,"../web3":10,"./formatters":17}],16:[function(require,module,exports){ +},{"../solidity/coder":1,"../utils/utils":6,"../web3":8,"./formatters":16}],15:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2351,7 +2423,7 @@ Filter.prototype.get = function (callback) { module.exports = Filter; -},{"../utils/utils":8,"./formatters":17,"./requestmanager":25}],17:[function(require,module,exports){ +},{"../utils/utils":6,"./formatters":16,"./requestmanager":24}],16:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2571,7 +2643,7 @@ module.exports = { }; -},{"../utils/config":7,"../utils/utils":8}],18:[function(require,module,exports){ +},{"../utils/config":5,"../utils/utils":6}],17:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2588,7 +2660,7 @@ module.exports = { You should have received a copy of the GNU Lesser General Public License along with ethereum.js. If not, see . */ -/** +/** * @file function.js * @author Marek Kotewicz * @date 2015 @@ -2613,18 +2685,23 @@ var SolidityFunction = function (json, address) { this._address = address; }; +SolidityFunction.prototype.extractCallback = function (args) { + if (utils.isFunction(args[args.length - 1])) { + return args.pop(); // modify the args array! + } +}; + /** * Should be used to create payload from arguments * * @method toPayload - * @param {...} solidity function params + * @param {Array} solidity function params * @param {Object} optional payload options */ -SolidityFunction.prototype.toPayload = function () { - var args = Array.prototype.slice.call(arguments); +SolidityFunction.prototype.toPayload = function (args) { var options = {}; if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) { - options = args.pop(); + options = args[args.length - 1]; } options.to = this._address; options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args); @@ -2641,19 +2718,41 @@ SolidityFunction.prototype.signature = function () { return web3.sha3(web3.fromAscii(this._name)).slice(2, 10); }; + +SolidityFunction.prototype.unpackOutput = function (output) { + if (output === null) { + return; + } + + output = output.length >= 2 ? output.slice(2) : output; + var result = coder.decodeParams(this._outputTypes, output); + return result.length === 1 ? result[0] : result; +}; + /** - * Should be used to call function - * + * Calls a contract function. + * * @method call - * @param {Object} options + * @param {...Object} Contract function arguments + * @param {function} If the last argument is a function, the contract function + * call will be asynchronous, and the callback will be passed the + * error and result. * @return {String} output bytes */ SolidityFunction.prototype.call = function () { - var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); - var output = web3.eth.call(payload); - output = output.length >= 2 ? output.slice(2) : output; - var result = coder.decodeParams(this._outputTypes, output); - return result.length === 1 ? result[0] : result; + var args = Array.prototype.slice.call(arguments); + var callback = this.extractCallback(args); + var payload = this.toPayload(args); + + if (!callback) { + var output = web3.eth.call(payload); + return this.unpackOutput(output); + } + + var self = this; + web3.eth.call(payload, function (error, output) { + callback(error, self.unpackOutput(output)); + }); }; /** @@ -2663,8 +2762,16 @@ SolidityFunction.prototype.call = function () { * @param {Object} options */ SolidityFunction.prototype.sendTransaction = function () { - var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); - web3.eth.sendTransaction(payload); + var args = Array.prototype.slice.call(arguments); + var callback = this.extractCallback(args); + var payload = this.toPayload(args); + + if (!callback) { + web3.eth.sendTransaction(payload); + return; + } + + web3.eth.sendTransaction(payload, callback); }; /** @@ -2679,7 +2786,7 @@ SolidityFunction.prototype.displayName = function () { /** * Should be used to get function type name - * + * * @method typeName * @return {String} type name of the function */ @@ -2687,6 +2794,25 @@ SolidityFunction.prototype.typeName = function () { return utils.extractTypeName(this._name); }; +/** + * Should be called to get rpc requests from solidity function + * + * @method request + * @returns {Object} + */ +SolidityFunction.prototype.request = function () { + var args = Array.prototype.slice.call(arguments); + var callback = this.extractCallback(args); + var payload = this.toPayload(args); + var format = this.unpackOutput.bind(this); + + return { + callback: callback, + payload: payload, + format: format + }; +}; + /** * Should be called to execute function * @@ -2694,7 +2820,7 @@ SolidityFunction.prototype.typeName = function () { */ SolidityFunction.prototype.execute = function () { var transaction = !this._constant; - + // send transaction if (transaction) { return this.sendTransaction.apply(this, Array.prototype.slice.call(arguments)); @@ -2712,6 +2838,7 @@ SolidityFunction.prototype.execute = function () { */ SolidityFunction.prototype.attachToContract = function (contract) { var execute = this.execute.bind(this); + execute.request = this.request.bind(this); execute.call = this.call.bind(this); execute.sendTransaction = this.sendTransaction.bind(this); var displayName = this.displayName(); @@ -2724,7 +2851,7 @@ SolidityFunction.prototype.attachToContract = function (contract) { module.exports = SolidityFunction; -},{"../solidity/coder":2,"../utils/utils":8,"../web3":10}],19:[function(require,module,exports){ +},{"../solidity/coder":1,"../utils/utils":6,"../web3":8}],18:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2816,7 +2943,7 @@ HttpProvider.prototype.sendAsync = function (payload, callback) { module.exports = HttpProvider; -},{"./errors":13,"xmlhttprequest":6}],20:[function(require,module,exports){ +},{"./errors":12,"xmlhttprequest":4}],19:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2909,7 +3036,7 @@ Jsonrpc.prototype.toBatchPayload = function (messages) { module.exports = Jsonrpc; -},{}],21:[function(require,module,exports){ +},{}],20:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2966,7 +3093,6 @@ Method.prototype.extractCallback = function (args) { if (utils.isFunction(args[args.length - 1])) { return args.pop(); // modify the args array! } - return null; }; /** @@ -3019,6 +3145,7 @@ Method.prototype.formatOutput = function (result) { */ Method.prototype.attachToObject = function (obj) { var func = this.send.bind(this); + func.request = this.request.bind(this); func.call = this.call; // that's ugly. filter.js uses it var name = this.name.split('.'); if (name.length > 1) { @@ -3049,6 +3176,19 @@ Method.prototype.toPayload = function (args) { }; }; +/** + * Should be called to create pure JSONRPC request which can be used in batch request + * + * @method request + * @param {...} params + * @return {Object} jsonrpc request + */ +Method.prototype.request = function () { + var payload = this.toPayload(Array.prototype.slice.call(arguments)); + payload.format = this.formatOutput.bind(this); + return payload; +}; + /** * Should send request to the API * @@ -3061,7 +3201,7 @@ Method.prototype.send = function () { if (payload.callback) { var self = this; return RequestManager.getInstance().sendAsync(payload, function (err, result) { - payload.callback(null, self.formatOutput(result)); + payload.callback(err, self.formatOutput(result)); }); } return this.formatOutput(RequestManager.getInstance().send(payload)); @@ -3070,7 +3210,7 @@ Method.prototype.send = function () { module.exports = Method; -},{"../utils/utils":8,"./errors":13,"./requestmanager":25}],22:[function(require,module,exports){ +},{"../utils/utils":6,"./errors":12,"./requestmanager":24}],21:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3120,7 +3260,7 @@ module.exports = { }; -},{"../utils/utils":8,"./property":23}],23:[function(require,module,exports){ +},{"../utils/utils":6,"./property":22}],22:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3186,16 +3326,23 @@ Property.prototype.formatOutput = function (result) { Property.prototype.attachToObject = function (obj) { var proto = { get: this.get.bind(this), - set: this.set.bind(this) }; - var name = this.name.split('.'); - if (name.length > 1) { - obj[name[0]] = obj[name[0]] || {}; - Object.defineProperty(obj[name[0]], name[1], proto); - } else { - Object.defineProperty(obj, name[0], proto); + var names = this.name.split('.'); + var name = names[0]; + if (names.length > 1) { + obj[names[0]] = obj[names[0]] || {}; + obj = obj[names[0]]; + name = names[1]; } + + Object.defineProperty(obj, name, proto); + + var toAsyncName = function (prefix, name) { + return prefix + name.charAt(0).toUpperCase() + name.slice(1); + }; + + obj[toAsyncName('get', name)] = this.getAsync.bind(this); }; /** @@ -3211,22 +3358,27 @@ Property.prototype.get = function () { }; /** - * Should be used to set value of the property + * Should be used to asynchrounously get value of property * - * @method set - * @param {Object} new value of the property + * @method getAsync + * @param {Function} */ -Property.prototype.set = function (value) { - return RequestManager.getInstance().send({ - method: this.setter, - params: [this.formatInput(value)] +Property.prototype.getAsync = function (callback) { + var self = this; + RequestManager.getInstance().sendAsync({ + method: this.getter + }, function (err, result) { + if (err) { + return callback(err); + } + callback(err, self.formatOutput(result)); }); }; module.exports = Property; -},{"./requestmanager":25}],24:[function(require,module,exports){ +},{"./requestmanager":24}],23:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3261,7 +3413,7 @@ QtSyncProvider.prototype.send = function (payload) { module.exports = QtSyncProvider; -},{}],25:[function(require,module,exports){ +},{}],24:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3369,6 +3521,33 @@ RequestManager.prototype.sendAsync = function (data, callback) { }); }; +/** + * Should be called to asynchronously send batch request + * + * @method sendBatch + * @param {Array} batch data + * @param {Function} callback + */ +RequestManager.prototype.sendBatch = function (data, callback) { + if (!this.provider) { + return callback(errors.InvalidProvider()); + } + + var payload = Jsonrpc.getInstance().toBatchPayload(data); + + this.provider.sendAsync(payload, function (err, results) { + if (err) { + return callback(err); + } + + if (!utils.isArray(results)) { + return callback(errors.InvalidResponse(results)); + } + + callback(err, results); + }); +}; + /** * Should be used to set provider of request manager * @@ -3482,7 +3661,7 @@ RequestManager.prototype.poll = function () { module.exports = RequestManager; -},{"../utils/config":7,"../utils/utils":8,"./errors":13,"./jsonrpc":20}],26:[function(require,module,exports){ +},{"../utils/config":5,"../utils/utils":6,"./errors":12,"./jsonrpc":19}],25:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3552,7 +3731,7 @@ module.exports = { }; -},{"./formatters":17,"./method":21}],27:[function(require,module,exports){ +},{"./formatters":16,"./method":20}],26:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3580,7 +3759,20 @@ var Method = require('./method'); /// @returns an array of objects describing web3.eth.filter api methods var eth = function () { var newFilterCall = function (args) { - return typeof args[0] === 'string' ? 'eth_newBlockFilter' : 'eth_newFilter'; + var type = args[0]; + + switch(type) { + case 'latest': + args.pop(); + this.params = 0; + return 'eth_newBlockFilter'; + case 'pending': + args.pop(); + this.params = 0; + return 'eth_newPendingTransactionFilter'; + default: + return 'eth_newFilter'; + } }; var newFilter = new Method({ @@ -3655,7 +3847,7 @@ module.exports = { }; -},{"./method":21}],28:[function(require,module,exports){ +},{"./method":20}],27:[function(require,module,exports){ },{}],"bignumber.js":[function(require,module,exports){ /*! bignumber.js v2.0.7 https://github.com/MikeMcl/bignumber.js/LICENCE */ @@ -6342,12 +6534,11 @@ module.exports = { } })(this); -},{"crypto":28}],"web3":[function(require,module,exports){ +},{"crypto":27}],"web3":[function(require,module,exports){ var web3 = require('./lib/web3'); web3.providers.HttpProvider = require('./lib/web3/httpprovider'); web3.providers.QtSyncProvider = require('./lib/web3/qtsync'); web3.eth.contract = require('./lib/web3/contract'); -web3.abi = require('./lib/solidity/abi'); // dont override global variable if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') { @@ -6357,7 +6548,7 @@ if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') { module.exports = web3; -},{"./lib/solidity/abi":1,"./lib/web3":10,"./lib/web3/contract":11,"./lib/web3/httpprovider":19,"./lib/web3/qtsync":24}]},{},["web3"]) +},{"./lib/web3":8,"./lib/web3/contract":10,"./lib/web3/httpprovider":18,"./lib/web3/qtsync":23}]},{},["web3"]) //# sourceMappingURL=web3.js.map \ No newline at end of file diff --git a/dist/web3.js.map b/dist/web3.js.map index 4efb07df1..e25fa3aed 100644 --- a/dist/web3.js.map +++ b/dist/web3.js.map @@ -2,16 +2,15 @@ "version": 3, "sources": [ "node_modules/browserify/node_modules/browser-pack/_prelude.js", - "lib/solidity/abi.js", "lib/solidity/coder.js", "lib/solidity/formatters.js", "lib/solidity/param.js", - "lib/solidity/utils.js", "lib/utils/browser-xhr.js", "lib/utils/config.js", "lib/utils/utils.js", "lib/version.json", "lib/web3.js", + "lib/web3/batch.js", "lib/web3/contract.js", "lib/web3/db.js", "lib/web3/errors.js", @@ -34,40 +33,39 @@ "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;;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", + "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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;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;AACA;;AC3dA;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;AACA;AACA;AACA;AACA;;ACzKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClHA;;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", "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 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.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/** \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/**\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.4.2\"\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');\nvar Batch = require('./web3/batch');\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;\nweb3.createBatch = function () {\n return new Batch();\n};\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 batch.js\n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar RequestManager = require('./requestmanager');\n\nvar Batch = function () {\n this.requests = [];\n};\n\n/**\n * Should be called to add create new request to batch request\n *\n * @method add\n * @param {Object} jsonrpc requet object\n */\nBatch.prototype.add = function (request) {\n this.requests.push(request);\n};\n\n/**\n * Should be called to execute batch request\n *\n * @method execute\n */\nBatch.prototype.execute = function () {\n var requests = this.requests;\n RequestManager.getInstance().sendBatch(requests, function (err, results) {\n results = results || [];\n requests.map(function (request, index) {\n return results[index] || {};\n }).map(function (result, index) {\n return requests[index].format ? requests[index].format(result.result) : result.result;\n }).forEach(function (result, index) {\n if (requests[index].callback) {\n requests[index].callback(err, result);\n }\n });\n }); \n};\n\nmodule.exports = Batch;\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 utils = require('../utils/utils');\nvar coder = require('../solidity/coder');\nvar SolidityEvent = require('./event');\nvar SolidityFunction = require('./function');\n\n/**\n * Should be called to encode constructor params\n *\n * @method encodeConstructorParams\n * @param {Array} abi\n * @param {Array} constructor params\n */\nvar encodeConstructorParams = function (abi, params) {\n return abi.filter(function (json) {\n return json.type === 'constructor' && json.inputs.length === params.length;\n }).map(function (json) {\n return json.inputs.map(function (input) {\n return input.type;\n });\n }).map(function (types) {\n return coder.encodeParams(types, params);\n })[0] || '';\n};\n\n/**\n * Should be called to add functions to contract object\n *\n * @method addFunctionsToContract\n * @param {Contract} contract\n * @param {Array} abi\n */\nvar addFunctionsToContract = function (contract, abi) {\n abi.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\n/**\n * Should be called to add events to contract object\n *\n * @method addEventsToContract\n * @param {Contract} contract\n * @param {Array} abi\n */\nvar addEventsToContract = function (contract, abi) {\n abi.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 * Should be called to create new ContractFactory\n *\n * @method contract\n * @param {Array} abi\n * @returns {ContractFactory} new contract factory\n */\nvar contract = function (abi) {\n return new ContractFactory(abi);\n};\n\n/**\n * Should be called to create new ContractFactory instance\n *\n * @method ContractFactory\n * @param {Array} abi\n */\nvar ContractFactory = function (abi) {\n this.abi = abi;\n};\n\n/**\n * Should be called to create new contract on a blockchain\n * \n * @method new\n * @param {Any} contract constructor param1 (optional)\n * @param {Any} contract constructor param2 (optional)\n * @param {Object} contract transaction object (required)\n * @param {Function} callback\n * @returns {Contract} returns contract if no callback was passed,\n * otherwise calls callback function (err, contract)\n */\nContractFactory.prototype.new = function () {\n // parse arguments\n var options = {}; // required!\n var callback;\n\n var args = Array.prototype.slice.call(arguments);\n if (utils.isFunction(args[args.length - 1])) {\n callback = args.pop();\n }\n\n var last = args[args.length - 1];\n if (utils.isObject(last) && !utils.isArray(last)) {\n options = args.pop();\n }\n\n // throw an error if there are no options\n\n var bytes = encodeConstructorParams(this.abi, args);\n options.data += bytes;\n\n if (!callback) {\n var address = web3.eth.sendTransaction(options);\n return this.at(address);\n }\n \n var self = this;\n web3.eth.sendTransaction(options, function (err, address) {\n if (err) {\n callback(err);\n }\n self.at(address, callback); \n }); \n};\n\n/**\n * Should be called to get access to existing contract on a blockchain\n *\n * @method at\n * @param {Address} contract address (required)\n * @param {Function} callback {optional)\n * @returns {Contract} returns contract if no callback was passed,\n * otherwise calls callback function (err, contract)\n */\nContractFactory.prototype.at = function (address, callback) {\n // TODO: address is required\n \n if (callback) {\n callback(null, new Contract(this.abi, address));\n } \n return new Contract(this.abi, address);\n};\n\n/**\n * Should be called to create new contract instance\n *\n * @method Contract\n * @param {Array} abi\n * @param {Address} contract address\n */\nvar Contract = function (abi, address) {\n this.address = address;\n addFunctionsToContract(this, abi);\n addEventsToContract(this, abi);\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: '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 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 estimateGas = new Method({\n name: 'estimateGas',\n call: 'eth_estimateGas',\n params: 1,\n inputFormatter: [formatters.inputTransactionFormatter],\n outputFormatter: utils.toDecimal\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 submitWork = new Method({\n name: 'submitWork',\n call: 'eth_submitWork',\n params: 3\n});\n\nvar getWork = new Method({\n name: 'getWork',\n call: 'eth_getWork',\n params: 0\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 estimateGas,\n sendTransaction,\n compileSolidity,\n compileLLL,\n compileSerpent,\n submitWork,\n getWork\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', '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/**\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\nSolidityFunction.prototype.extractCallback = function (args) {\n if (utils.isFunction(args[args.length - 1])) {\n return args.pop(); // modify the args array!\n }\n};\n\n/**\n * Should be used to create payload from arguments\n *\n * @method toPayload\n * @param {Array} solidity function params\n * @param {Object} optional payload options\n */\nSolidityFunction.prototype.toPayload = function (args) {\n var options = {};\n if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) {\n options = args[args.length - 1];\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\nSolidityFunction.prototype.unpackOutput = function (output) {\n if (output === null) {\n return;\n }\n\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 * Calls a contract function.\n *\n * @method call\n * @param {...Object} Contract function arguments\n * @param {function} If the last argument is a function, the contract function\n * call will be asynchronous, and the callback will be passed the\n * error and result.\n * @return {String} output bytes\n */\nSolidityFunction.prototype.call = function () {\n var args = Array.prototype.slice.call(arguments);\n var callback = this.extractCallback(args);\n var payload = this.toPayload(args);\n\n if (!callback) {\n var output = web3.eth.call(payload);\n return this.unpackOutput(output);\n } \n \n var self = this;\n web3.eth.call(payload, function (error, output) {\n callback(error, self.unpackOutput(output));\n });\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 args = Array.prototype.slice.call(arguments);\n var callback = this.extractCallback(args);\n var payload = this.toPayload(args);\n\n if (!callback) {\n web3.eth.sendTransaction(payload);\n return;\n }\n\n web3.eth.sendTransaction(payload, callback);\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 get rpc requests from solidity function\n *\n * @method request\n * @returns {Object}\n */\nSolidityFunction.prototype.request = function () {\n var args = Array.prototype.slice.call(arguments);\n var callback = this.extractCallback(args);\n var payload = this.toPayload(args);\n var format = this.unpackOutput.bind(this);\n \n return {\n callback: callback,\n payload: payload, \n format: format\n };\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.request = this.request.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\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/**\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};\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.request = this.request.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 be called to create pure JSONRPC request which can be used in batch request\n *\n * @method request\n * @param {...} params\n * @return {Object} jsonrpc request\n */\nMethod.prototype.request = function () {\n var payload = this.toPayload(Array.prototype.slice.call(arguments));\n payload.format = this.formatOutput.bind(this);\n return payload;\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(err, 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", - "/*\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 property.js\n * @author Fabian Vogelsteller \n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar RequestManager = require('./requestmanager');\n\nvar Property = function (options) {\n this.name = options.name;\n this.getter = options.getter;\n this.setter = options.setter;\n this.outputFormatter = options.outputFormatter;\n this.inputFormatter = options.inputFormatter;\n};\n\n/**\n * Should be called to format input args of method\n * \n * @method formatInput\n * @param {Array}\n * @return {Array}\n */\nProperty.prototype.formatInput = function (arg) {\n return this.inputFormatter ? this.inputFormatter(arg) : arg;\n};\n\n/**\n * Should be called to format output(result) of method\n *\n * @method formatOutput\n * @param {Object}\n * @return {Object}\n */\nProperty.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 */\nProperty.prototype.attachToObject = function (obj) {\n var proto = {\n get: this.get.bind(this),\n set: this.set.bind(this)\n };\n\n var name = this.name.split('.');\n if (name.length > 1) {\n obj[name[0]] = obj[name[0]] || {};\n Object.defineProperty(obj[name[0]], name[1], proto); \n } else {\n Object.defineProperty(obj, name[0], proto);\n }\n};\n\n/**\n * Should be used to get value of the property\n *\n * @method get\n * @return {Object} value of the property\n */\nProperty.prototype.get = function () {\n return this.formatOutput(RequestManager.getInstance().send({\n method: this.getter\n }));\n};\n\n/**\n * Should be used to set value of the property\n *\n * @method set\n * @param {Object} new value of the property\n */\nProperty.prototype.set = function (value) {\n return RequestManager.getInstance().send({\n method: this.setter,\n params: [this.formatInput(value)]\n });\n};\n\nmodule.exports = Property;\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 property.js\n * @author Fabian Vogelsteller \n * @author Marek Kotewicz \n * @date 2015\n */\n\nvar RequestManager = require('./requestmanager');\n\nvar Property = function (options) {\n this.name = options.name;\n this.getter = options.getter;\n this.setter = options.setter;\n this.outputFormatter = options.outputFormatter;\n this.inputFormatter = options.inputFormatter;\n};\n\n/**\n * Should be called to format input args of method\n * \n * @method formatInput\n * @param {Array}\n * @return {Array}\n */\nProperty.prototype.formatInput = function (arg) {\n return this.inputFormatter ? this.inputFormatter(arg) : arg;\n};\n\n/**\n * Should be called to format output(result) of method\n *\n * @method formatOutput\n * @param {Object}\n * @return {Object}\n */\nProperty.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 */\nProperty.prototype.attachToObject = function (obj) {\n var proto = {\n get: this.get.bind(this),\n };\n\n var names = this.name.split('.');\n var name = names[0];\n if (names.length > 1) {\n obj[names[0]] = obj[names[0]] || {};\n obj = obj[names[0]];\n name = names[1];\n }\n \n Object.defineProperty(obj, name, proto);\n\n var toAsyncName = function (prefix, name) {\n return prefix + name.charAt(0).toUpperCase() + name.slice(1);\n };\n\n obj[toAsyncName('get', name)] = this.getAsync.bind(this);\n};\n\n/**\n * Should be used to get value of the property\n *\n * @method get\n * @return {Object} value of the property\n */\nProperty.prototype.get = function () {\n return this.formatOutput(RequestManager.getInstance().send({\n method: this.getter\n }));\n};\n\n/**\n * Should be used to asynchrounously get value of property\n *\n * @method getAsync\n * @param {Function}\n */\nProperty.prototype.getAsync = function (callback) {\n var self = this;\n RequestManager.getInstance().sendAsync({\n method: this.getter\n }, function (err, result) {\n if (err) {\n return callback(err);\n }\n callback(err, self.formatOutput(result));\n });\n};\n\nmodule.exports = Property;\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 qtsync.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\nvar QtSyncProvider = function () {\n};\n\nQtSyncProvider.prototype.send = function (payload) {\n var result = navigator.qt.callMethod(JSON.stringify(payload));\n return JSON.parse(result);\n};\n\nmodule.exports = QtSyncProvider;\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 requestmanager.js\n * @author Jeffrey Wilcke \n * @author Marek Kotewicz \n * @author Marian Oancea \n * @author Fabian Vogelsteller \n * @author Gav Wood \n * @date 2014\n */\n\nvar Jsonrpc = require('./jsonrpc');\nvar utils = require('../utils/utils');\nvar c = require('../utils/config');\nvar errors = require('./errors');\n\n/**\n * It's responsible for passing messages to providers\n * It's also responsible for polling the ethereum node for incoming messages\n * Default poll timeout is 1 second\n * Singleton\n */\nvar RequestManager = function (provider) {\n // singleton pattern\n if (arguments.callee._singletonInstance) {\n return arguments.callee._singletonInstance;\n }\n arguments.callee._singletonInstance = this;\n\n this.provider = provider;\n this.polls = [];\n this.timeout = null;\n this.poll();\n};\n\n/**\n * @return {RequestManager} singleton\n */\nRequestManager.getInstance = function () {\n var instance = new RequestManager();\n return instance;\n};\n\n/**\n * Should be used to synchronously send request\n *\n * @method send\n * @param {Object} data\n * @return {Object}\n */\nRequestManager.prototype.send = function (data) {\n if (!this.provider) {\n console.error(errors.InvalidProvider());\n return null;\n }\n\n var payload = Jsonrpc.getInstance().toPayload(data.method, data.params);\n var result = this.provider.send(payload);\n\n if (!Jsonrpc.getInstance().isValidResponse(result)) {\n throw errors.InvalidResponse(result);\n }\n\n return result.result;\n};\n\n/**\n * Should be used to asynchronously send request\n *\n * @method sendAsync\n * @param {Object} data\n * @param {Function} callback\n */\nRequestManager.prototype.sendAsync = function (data, callback) {\n if (!this.provider) {\n return callback(errors.InvalidProvider());\n }\n\n var payload = Jsonrpc.getInstance().toPayload(data.method, data.params);\n this.provider.sendAsync(payload, function (err, result) {\n if (err) {\n return callback(err);\n }\n \n if (!Jsonrpc.getInstance().isValidResponse(result)) {\n return callback(errors.InvalidResponse(result));\n }\n\n callback(null, result.result);\n });\n};\n\n/**\n * Should be used to set provider of request manager\n *\n * @method setProvider\n * @param {Object}\n */\nRequestManager.prototype.setProvider = function (p) {\n this.provider = p;\n};\n\n/*jshint maxparams:4 */\n\n/**\n * Should be used to start polling\n *\n * @method startPolling\n * @param {Object} data\n * @param {Number} pollId\n * @param {Function} callback\n * @param {Function} uninstall\n *\n * @todo cleanup number of params\n */\nRequestManager.prototype.startPolling = function (data, pollId, callback, uninstall) {\n this.polls.push({data: data, id: pollId, callback: callback, uninstall: uninstall});\n};\n/*jshint maxparams:3 */\n\n/**\n * Should be used to stop polling for filter with given id\n *\n * @method stopPolling\n * @param {Number} pollId\n */\nRequestManager.prototype.stopPolling = function (pollId) {\n for (var i = this.polls.length; i--;) {\n var poll = this.polls[i];\n if (poll.id === pollId) {\n this.polls.splice(i, 1);\n }\n }\n};\n\n/**\n * Should be called to reset polling mechanism of request manager\n *\n * @method reset\n */\nRequestManager.prototype.reset = function () {\n this.polls.forEach(function (poll) {\n poll.uninstall(poll.id); \n });\n this.polls = [];\n\n if (this.timeout) {\n clearTimeout(this.timeout);\n this.timeout = null;\n }\n this.poll();\n};\n\n/**\n * Should be called to poll for changes on filter with given id\n *\n * @method poll\n */\nRequestManager.prototype.poll = function () {\n this.timeout = setTimeout(this.poll.bind(this), c.ETH_POLLING_TIMEOUT);\n\n if (!this.polls.length) {\n return;\n }\n\n if (!this.provider) {\n console.error(errors.InvalidProvider());\n return;\n }\n\n var payload = Jsonrpc.getInstance().toBatchPayload(this.polls.map(function (data) {\n return data.data;\n }));\n\n var self = this;\n this.provider.sendAsync(payload, function (error, results) {\n // TODO: console log?\n if (error) {\n return;\n }\n \n if (!utils.isArray(results)) {\n throw errors.InvalidResponse(results);\n }\n\n results.map(function (result, index) {\n result.callback = self.polls[index].callback;\n return result;\n }).filter(function (result) {\n var valid = Jsonrpc.getInstance().isValidResponse(result);\n if (!valid) {\n result.callback(errors.InvalidResponse(result));\n }\n return valid;\n }).filter(function (result) {\n return utils.isArray(result.result) && result.result.length > 0;\n }).forEach(function (result) {\n result.callback(null, result.result);\n });\n });\n};\n\nmodule.exports = RequestManager;\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 requestmanager.js\n * @author Jeffrey Wilcke \n * @author Marek Kotewicz \n * @author Marian Oancea \n * @author Fabian Vogelsteller \n * @author Gav Wood \n * @date 2014\n */\n\nvar Jsonrpc = require('./jsonrpc');\nvar utils = require('../utils/utils');\nvar c = require('../utils/config');\nvar errors = require('./errors');\n\n/**\n * It's responsible for passing messages to providers\n * It's also responsible for polling the ethereum node for incoming messages\n * Default poll timeout is 1 second\n * Singleton\n */\nvar RequestManager = function (provider) {\n // singleton pattern\n if (arguments.callee._singletonInstance) {\n return arguments.callee._singletonInstance;\n }\n arguments.callee._singletonInstance = this;\n\n this.provider = provider;\n this.polls = [];\n this.timeout = null;\n this.poll();\n};\n\n/**\n * @return {RequestManager} singleton\n */\nRequestManager.getInstance = function () {\n var instance = new RequestManager();\n return instance;\n};\n\n/**\n * Should be used to synchronously send request\n *\n * @method send\n * @param {Object} data\n * @return {Object}\n */\nRequestManager.prototype.send = function (data) {\n if (!this.provider) {\n console.error(errors.InvalidProvider());\n return null;\n }\n\n var payload = Jsonrpc.getInstance().toPayload(data.method, data.params);\n var result = this.provider.send(payload);\n\n if (!Jsonrpc.getInstance().isValidResponse(result)) {\n throw errors.InvalidResponse(result);\n }\n\n return result.result;\n};\n\n/**\n * Should be used to asynchronously send request\n *\n * @method sendAsync\n * @param {Object} data\n * @param {Function} callback\n */\nRequestManager.prototype.sendAsync = function (data, callback) {\n if (!this.provider) {\n return callback(errors.InvalidProvider());\n }\n\n var payload = Jsonrpc.getInstance().toPayload(data.method, data.params);\n this.provider.sendAsync(payload, function (err, result) {\n if (err) {\n return callback(err);\n }\n \n if (!Jsonrpc.getInstance().isValidResponse(result)) {\n return callback(errors.InvalidResponse(result));\n }\n\n callback(null, result.result);\n });\n};\n\n/**\n * Should be called to asynchronously send batch request\n *\n * @method sendBatch\n * @param {Array} batch data\n * @param {Function} callback\n */\nRequestManager.prototype.sendBatch = function (data, callback) {\n if (!this.provider) {\n return callback(errors.InvalidProvider());\n }\n\n var payload = Jsonrpc.getInstance().toBatchPayload(data);\n\n this.provider.sendAsync(payload, function (err, results) {\n if (err) {\n return callback(err);\n }\n\n if (!utils.isArray(results)) {\n return callback(errors.InvalidResponse(results));\n }\n\n callback(err, results);\n }); \n};\n\n/**\n * Should be used to set provider of request manager\n *\n * @method setProvider\n * @param {Object}\n */\nRequestManager.prototype.setProvider = function (p) {\n this.provider = p;\n};\n\n/*jshint maxparams:4 */\n\n/**\n * Should be used to start polling\n *\n * @method startPolling\n * @param {Object} data\n * @param {Number} pollId\n * @param {Function} callback\n * @param {Function} uninstall\n *\n * @todo cleanup number of params\n */\nRequestManager.prototype.startPolling = function (data, pollId, callback, uninstall) {\n this.polls.push({data: data, id: pollId, callback: callback, uninstall: uninstall});\n};\n/*jshint maxparams:3 */\n\n/**\n * Should be used to stop polling for filter with given id\n *\n * @method stopPolling\n * @param {Number} pollId\n */\nRequestManager.prototype.stopPolling = function (pollId) {\n for (var i = this.polls.length; i--;) {\n var poll = this.polls[i];\n if (poll.id === pollId) {\n this.polls.splice(i, 1);\n }\n }\n};\n\n/**\n * Should be called to reset polling mechanism of request manager\n *\n * @method reset\n */\nRequestManager.prototype.reset = function () {\n this.polls.forEach(function (poll) {\n poll.uninstall(poll.id); \n });\n this.polls = [];\n\n if (this.timeout) {\n clearTimeout(this.timeout);\n this.timeout = null;\n }\n this.poll();\n};\n\n/**\n * Should be called to poll for changes on filter with given id\n *\n * @method poll\n */\nRequestManager.prototype.poll = function () {\n this.timeout = setTimeout(this.poll.bind(this), c.ETH_POLLING_TIMEOUT);\n\n if (!this.polls.length) {\n return;\n }\n\n if (!this.provider) {\n console.error(errors.InvalidProvider());\n return;\n }\n\n var payload = Jsonrpc.getInstance().toBatchPayload(this.polls.map(function (data) {\n return data.data;\n }));\n\n var self = this;\n this.provider.sendAsync(payload, function (error, results) {\n // TODO: console log?\n if (error) {\n return;\n }\n \n if (!utils.isArray(results)) {\n throw errors.InvalidResponse(results);\n }\n\n results.map(function (result, index) {\n result.callback = self.polls[index].callback;\n return result;\n }).filter(function (result) {\n var valid = Jsonrpc.getInstance().isValidResponse(result);\n if (!valid) {\n result.callback(errors.InvalidResponse(result));\n }\n return valid;\n }).filter(function (result) {\n return utils.isArray(result.result) && result.result.length > 0;\n }).forEach(function (result) {\n result.callback(null, result.result);\n });\n });\n};\n\nmodule.exports = RequestManager;\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 shh.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar Method = require('./method');\nvar formatters = require('./formatters');\n\nvar post = new Method({\n name: 'post', \n call: 'shh_post', \n params: 1,\n inputFormatter: [formatters.inputPostFormatter]\n});\n\nvar newIdentity = new Method({\n name: 'newIdentity',\n call: 'shh_newIdentity',\n params: 0\n});\n\nvar hasIdentity = new Method({\n name: 'hasIdentity',\n call: 'shh_hasIdentity',\n params: 1\n});\n\nvar newGroup = new Method({\n name: 'newGroup',\n call: 'shh_newGroup',\n params: 0\n});\n\nvar addToGroup = new Method({\n name: 'addToGroup',\n call: 'shh_addToGroup',\n params: 0\n});\n\nvar methods = [\n post,\n newIdentity,\n hasIdentity,\n newGroup,\n addToGroup\n];\n\nmodule.exports = {\n methods: methods\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 watches.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar Method = require('./method');\n\n/// @returns an array of objects describing web3.eth.filter api methods\nvar eth = function () {\n var newFilterCall = function (args) {\n return typeof args[0] === 'string' ? 'eth_newBlockFilter' : 'eth_newFilter';\n };\n\n var newFilter = new Method({\n name: 'newFilter',\n call: newFilterCall,\n params: 1\n });\n\n var uninstallFilter = new Method({\n name: 'uninstallFilter',\n call: 'eth_uninstallFilter',\n params: 1\n });\n\n var getLogs = new Method({\n name: 'getLogs',\n call: 'eth_getFilterLogs',\n params: 1\n });\n\n var poll = new Method({\n name: 'poll',\n call: 'eth_getFilterChanges',\n params: 1\n });\n\n return [\n newFilter,\n uninstallFilter,\n getLogs,\n poll\n ];\n};\n\n/// @returns an array of objects describing web3.shh.watch api methods\nvar shh = function () {\n var newFilter = new Method({\n name: 'newFilter',\n call: 'shh_newFilter',\n params: 1\n });\n\n var uninstallFilter = new Method({\n name: 'uninstallFilter',\n call: 'shh_uninstallFilter',\n params: 1\n });\n\n var getLogs = new Method({\n name: 'getLogs',\n call: 'shh_getMessages',\n params: 1\n });\n\n var poll = new Method({\n name: 'poll',\n call: 'shh_getFilterChanges',\n params: 1\n });\n\n return [\n newFilter,\n uninstallFilter,\n getLogs,\n poll\n ];\n};\n\nmodule.exports = {\n eth: eth,\n shh: shh\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 watches.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar Method = require('./method');\n\n/// @returns an array of objects describing web3.eth.filter api methods\nvar eth = function () {\n var newFilterCall = function (args) {\n var type = args[0];\n\n switch(type) {\n case 'latest':\n args.pop();\n this.params = 0;\n return 'eth_newBlockFilter';\n case 'pending':\n args.pop();\n this.params = 0;\n return 'eth_newPendingTransactionFilter';\n default:\n return 'eth_newFilter';\n }\n };\n\n var newFilter = new Method({\n name: 'newFilter',\n call: newFilterCall,\n params: 1\n });\n\n var uninstallFilter = new Method({\n name: 'uninstallFilter',\n call: 'eth_uninstallFilter',\n params: 1\n });\n\n var getLogs = new Method({\n name: 'getLogs',\n call: 'eth_getFilterLogs',\n params: 1\n });\n\n var poll = new Method({\n name: 'poll',\n call: 'eth_getFilterChanges',\n params: 1\n });\n\n return [\n newFilter,\n uninstallFilter,\n getLogs,\n poll\n ];\n};\n\n/// @returns an array of objects describing web3.shh.watch api methods\nvar shh = function () {\n var newFilter = new Method({\n name: 'newFilter',\n call: 'shh_newFilter',\n params: 1\n });\n\n var uninstallFilter = new Method({\n name: 'uninstallFilter',\n call: 'shh_uninstallFilter',\n params: 1\n });\n\n var getLogs = new Method({\n name: 'getLogs',\n call: 'shh_getMessages',\n params: 1\n });\n\n var poll = new Method({\n name: 'poll',\n call: 'shh_getFilterChanges',\n params: 1\n });\n\n return [\n newFilter,\n uninstallFilter,\n getLogs,\n poll\n ];\n};\n\nmodule.exports = {\n eth: eth,\n shh: shh\n};\n\n", null, "/*! bignumber.js v2.0.7 https://github.com/MikeMcl/bignumber.js/LICENCE */\n\n;(function (global) {\n 'use strict';\n\n /*\n bignumber.js v2.0.7\n A JavaScript library for arbitrary-precision arithmetic.\n https://github.com/MikeMcl/bignumber.js\n Copyright (c) 2015 Michael Mclaughlin \n MIT Expat Licence\n */\n\n\n var BigNumber, crypto, parseNumeric,\n isNumeric = /^-?(\\d+(\\.\\d*)?|\\.\\d+)(e[+-]?\\d+)?$/i,\n mathceil = Math.ceil,\n mathfloor = Math.floor,\n notBool = ' not a boolean or binary digit',\n roundingMode = 'rounding mode',\n tooManyDigits = 'number type has more than 15 significant digits',\n ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_',\n BASE = 1e14,\n LOG_BASE = 14,\n MAX_SAFE_INTEGER = 0x1fffffffffffff, // 2^53 - 1\n // MAX_INT32 = 0x7fffffff, // 2^31 - 1\n POWS_TEN = [1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13],\n SQRT_BASE = 1e7,\n\n /*\n * The limit on the value of DECIMAL_PLACES, TO_EXP_NEG, TO_EXP_POS, MIN_EXP, MAX_EXP, and\n * the arguments to toExponential, toFixed, toFormat, and toPrecision, beyond which an\n * exception is thrown (if ERRORS is true).\n */\n MAX = 1E9; // 0 to MAX_INT32\n\n\n /*\n * Create and return a BigNumber constructor.\n */\n function another(configObj) {\n var div,\n\n // id tracks the caller function, so its name can be included in error messages.\n id = 0,\n P = BigNumber.prototype,\n ONE = new BigNumber(1),\n\n\n /********************************* EDITABLE DEFAULTS **********************************/\n\n\n /*\n * The default values below must be integers within the inclusive ranges stated.\n * The values can also be changed at run-time using BigNumber.config.\n */\n\n // The maximum number of decimal places for operations involving division.\n DECIMAL_PLACES = 20, // 0 to MAX\n\n /*\n * The rounding mode used when rounding to the above decimal places, and when using\n * toExponential, toFixed, toFormat and toPrecision, and round (default value).\n * UP 0 Away from zero.\n * DOWN 1 Towards zero.\n * CEIL 2 Towards +Infinity.\n * FLOOR 3 Towards -Infinity.\n * HALF_UP 4 Towards nearest neighbour. If equidistant, up.\n * HALF_DOWN 5 Towards nearest neighbour. If equidistant, down.\n * HALF_EVEN 6 Towards nearest neighbour. If equidistant, towards even neighbour.\n * HALF_CEIL 7 Towards nearest neighbour. If equidistant, towards +Infinity.\n * HALF_FLOOR 8 Towards nearest neighbour. If equidistant, towards -Infinity.\n */\n ROUNDING_MODE = 4, // 0 to 8\n\n // EXPONENTIAL_AT : [TO_EXP_NEG , TO_EXP_POS]\n\n // The exponent value at and beneath which toString returns exponential notation.\n // Number type: -7\n TO_EXP_NEG = -7, // 0 to -MAX\n\n // The exponent value at and above which toString returns exponential notation.\n // Number type: 21\n TO_EXP_POS = 21, // 0 to MAX\n\n // RANGE : [MIN_EXP, MAX_EXP]\n\n // The minimum exponent value, beneath which underflow to zero occurs.\n // Number type: -324 (5e-324)\n MIN_EXP = -1e7, // -1 to -MAX\n\n // The maximum exponent value, above which overflow to Infinity occurs.\n // Number type: 308 (1.7976931348623157e+308)\n // For MAX_EXP > 1e7, e.g. new BigNumber('1e100000000').plus(1) may be slow.\n MAX_EXP = 1e7, // 1 to MAX\n\n // Whether BigNumber Errors are ever thrown.\n ERRORS = true, // true or false\n\n // Change to intValidatorNoErrors if ERRORS is false.\n isValidInt = intValidatorWithErrors, // intValidatorWithErrors/intValidatorNoErrors\n\n // Whether to use cryptographically-secure random number generation, if available.\n CRYPTO = false, // true or false\n\n /*\n * The modulo mode used when calculating the modulus: a mod n.\n * The quotient (q = a / n) is calculated according to the corresponding rounding mode.\n * The remainder (r) is calculated as: r = a - n * q.\n *\n * UP 0 The remainder is positive if the dividend is negative, else is negative.\n * DOWN 1 The remainder has the same sign as the dividend.\n * This modulo mode is commonly known as 'truncated division' and is\n * equivalent to (a % n) in JavaScript.\n * FLOOR 3 The remainder has the same sign as the divisor (Python %).\n * HALF_EVEN 6 This modulo mode implements the IEEE 754 remainder function.\n * EUCLID 9 Euclidian division. q = sign(n) * floor(a / abs(n)).\n * The remainder is always positive.\n *\n * The truncated division, floored division, Euclidian division and IEEE 754 remainder\n * modes are commonly used for the modulus operation.\n * Although the other rounding modes can also be used, they may not give useful results.\n */\n MODULO_MODE = 1, // 0 to 9\n\n // The maximum number of significant digits of the result of the toPower operation.\n // If POW_PRECISION is 0, there will be unlimited significant digits.\n POW_PRECISION = 100, // 0 to MAX\n\n // The format specification used by the BigNumber.prototype.toFormat method.\n FORMAT = {\n decimalSeparator: '.',\n groupSeparator: ',',\n groupSize: 3,\n secondaryGroupSize: 0,\n fractionGroupSeparator: '\\xA0', // non-breaking space\n fractionGroupSize: 0\n };\n\n\n /******************************************************************************************/\n\n\n // CONSTRUCTOR\n\n\n /*\n * The BigNumber constructor and exported function.\n * Create and return a new instance of a BigNumber object.\n *\n * n {number|string|BigNumber} A numeric value.\n * [b] {number} The base of n. Integer, 2 to 64 inclusive.\n */\n function BigNumber( n, b ) {\n var c, e, i, num, len, str,\n x = this;\n\n // Enable constructor usage without new.\n if ( !( x instanceof BigNumber ) ) {\n\n // 'BigNumber() constructor call without new: {n}'\n if (ERRORS) raise( 26, 'constructor call without new', n );\n return new BigNumber( n, b );\n }\n\n // 'new BigNumber() base not an integer: {b}'\n // 'new BigNumber() base out of range: {b}'\n if ( b == null || !isValidInt( b, 2, 64, id, 'base' ) ) {\n\n // Duplicate.\n if ( n instanceof BigNumber ) {\n x.s = n.s;\n x.e = n.e;\n x.c = ( n = n.c ) ? n.slice() : n;\n id = 0;\n return;\n }\n\n if ( ( num = typeof n == 'number' ) && n * 0 == 0 ) {\n x.s = 1 / n < 0 ? ( n = -n, -1 ) : 1;\n\n // Fast path for integers.\n if ( n === ~~n ) {\n for ( e = 0, i = n; i >= 10; i /= 10, e++ );\n x.e = e;\n x.c = [n];\n id = 0;\n return;\n }\n\n str = n + '';\n } else {\n if ( !isNumeric.test( str = n + '' ) ) return parseNumeric( x, str, num );\n x.s = str.charCodeAt(0) === 45 ? ( str = str.slice(1), -1 ) : 1;\n }\n } else {\n b = b | 0;\n str = n + '';\n\n // Ensure return value is rounded to DECIMAL_PLACES as with other bases.\n // Allow exponential notation to be used with base 10 argument.\n if ( b == 10 ) {\n x = new BigNumber( n instanceof BigNumber ? n : str );\n return round( x, DECIMAL_PLACES + x.e + 1, ROUNDING_MODE );\n }\n\n // Avoid potential interpretation of Infinity and NaN as base 44+ values.\n // Any number in exponential form will fail due to the [Ee][+-].\n if ( ( num = typeof n == 'number' ) && n * 0 != 0 ||\n !( new RegExp( '^-?' + ( c = '[' + ALPHABET.slice( 0, b ) + ']+' ) +\n '(?:\\\\.' + c + ')?$',b < 37 ? 'i' : '' ) ).test(str) ) {\n return parseNumeric( x, str, num, b );\n }\n\n if (num) {\n x.s = 1 / n < 0 ? ( str = str.slice(1), -1 ) : 1;\n\n if ( ERRORS && str.replace( /^0\\.0*|\\./, '' ).length > 15 ) {\n\n // 'new BigNumber() number type has more than 15 significant digits: {n}'\n raise( id, tooManyDigits, n );\n }\n\n // Prevent later check for length on converted number.\n num = false;\n } else {\n x.s = str.charCodeAt(0) === 45 ? ( str = str.slice(1), -1 ) : 1;\n }\n\n str = convertBase( str, 10, b, x.s );\n }\n\n // Decimal point?\n if ( ( e = str.indexOf('.') ) > -1 ) str = str.replace( '.', '' );\n\n // Exponential form?\n if ( ( i = str.search( /e/i ) ) > 0 ) {\n\n // Determine exponent.\n if ( e < 0 ) e = i;\n e += +str.slice( i + 1 );\n str = str.substring( 0, i );\n } else if ( e < 0 ) {\n\n // Integer.\n e = str.length;\n }\n\n // Determine leading zeros.\n for ( i = 0; str.charCodeAt(i) === 48; i++ );\n\n // Determine trailing zeros.\n for ( len = str.length; str.charCodeAt(--len) === 48; );\n str = str.slice( i, len + 1 );\n\n if (str) {\n len = str.length;\n\n // Disallow numbers with over 15 significant digits if number type.\n // 'new BigNumber() number type has more than 15 significant digits: {n}'\n if ( num && ERRORS && len > 15 ) raise( id, tooManyDigits, x.s * n );\n\n e = e - i - 1;\n\n // Overflow?\n if ( e > MAX_EXP ) {\n\n // Infinity.\n x.c = x.e = null;\n\n // Underflow?\n } else if ( e < MIN_EXP ) {\n\n // Zero.\n x.c = [ x.e = 0 ];\n } else {\n x.e = e;\n x.c = [];\n\n // Transform base\n\n // e is the base 10 exponent.\n // i is where to slice str to get the first element of the coefficient array.\n i = ( e + 1 ) % LOG_BASE;\n if ( e < 0 ) i += LOG_BASE;\n\n if ( i < len ) {\n if (i) x.c.push( +str.slice( 0, i ) );\n\n for ( len -= LOG_BASE; i < len; ) {\n x.c.push( +str.slice( i, i += LOG_BASE ) );\n }\n\n str = str.slice(i);\n i = LOG_BASE - str.length;\n } else {\n i -= len;\n }\n\n for ( ; i--; str += '0' );\n x.c.push( +str );\n }\n } else {\n\n // Zero.\n x.c = [ x.e = 0 ];\n }\n\n id = 0;\n }\n\n\n // CONSTRUCTOR PROPERTIES\n\n\n BigNumber.another = another;\n\n BigNumber.ROUND_UP = 0;\n BigNumber.ROUND_DOWN = 1;\n BigNumber.ROUND_CEIL = 2;\n BigNumber.ROUND_FLOOR = 3;\n BigNumber.ROUND_HALF_UP = 4;\n BigNumber.ROUND_HALF_DOWN = 5;\n BigNumber.ROUND_HALF_EVEN = 6;\n BigNumber.ROUND_HALF_CEIL = 7;\n BigNumber.ROUND_HALF_FLOOR = 8;\n BigNumber.EUCLID = 9;\n\n\n /*\n * Configure infrequently-changing library-wide settings.\n *\n * Accept an object or an argument list, with one or many of the following properties or\n * parameters respectively:\n *\n * DECIMAL_PLACES {number} Integer, 0 to MAX inclusive\n * ROUNDING_MODE {number} Integer, 0 to 8 inclusive\n * EXPONENTIAL_AT {number|number[]} Integer, -MAX to MAX inclusive or\n * [integer -MAX to 0 incl., 0 to MAX incl.]\n * RANGE {number|number[]} Non-zero integer, -MAX to MAX inclusive or\n * [integer -MAX to -1 incl., integer 1 to MAX incl.]\n * ERRORS {boolean|number} true, false, 1 or 0\n * CRYPTO {boolean|number} true, false, 1 or 0\n * MODULO_MODE {number} 0 to 9 inclusive\n * POW_PRECISION {number} 0 to MAX inclusive\n * FORMAT {object} See BigNumber.prototype.toFormat\n * decimalSeparator {string}\n * groupSeparator {string}\n * groupSize {number}\n * secondaryGroupSize {number}\n * fractionGroupSeparator {string}\n * fractionGroupSize {number}\n *\n * (The values assigned to the above FORMAT object properties are not checked for validity.)\n *\n * E.g.\n * BigNumber.config(20, 4) is equivalent to\n * BigNumber.config({ DECIMAL_PLACES : 20, ROUNDING_MODE : 4 })\n *\n * Ignore properties/parameters set to null or undefined.\n * Return an object with the properties current values.\n */\n BigNumber.config = function () {\n var v, p,\n i = 0,\n r = {},\n a = arguments,\n o = a[0],\n has = o && typeof o == 'object'\n ? function () { if ( o.hasOwnProperty(p) ) return ( v = o[p] ) != null; }\n : function () { if ( a.length > i ) return ( v = a[i++] ) != null; };\n\n // DECIMAL_PLACES {number} Integer, 0 to MAX inclusive.\n // 'config() DECIMAL_PLACES not an integer: {v}'\n // 'config() DECIMAL_PLACES out of range: {v}'\n if ( has( p = 'DECIMAL_PLACES' ) && isValidInt( v, 0, MAX, 2, p ) ) {\n DECIMAL_PLACES = v | 0;\n }\n r[p] = DECIMAL_PLACES;\n\n // ROUNDING_MODE {number} Integer, 0 to 8 inclusive.\n // 'config() ROUNDING_MODE not an integer: {v}'\n // 'config() ROUNDING_MODE out of range: {v}'\n if ( has( p = 'ROUNDING_MODE' ) && isValidInt( v, 0, 8, 2, p ) ) {\n ROUNDING_MODE = v | 0;\n }\n r[p] = ROUNDING_MODE;\n\n // EXPONENTIAL_AT {number|number[]}\n // Integer, -MAX to MAX inclusive or [integer -MAX to 0 inclusive, 0 to MAX inclusive].\n // 'config() EXPONENTIAL_AT not an integer: {v}'\n // 'config() EXPONENTIAL_AT out of range: {v}'\n if ( has( p = 'EXPONENTIAL_AT' ) ) {\n\n if ( isArray(v) ) {\n if ( isValidInt( v[0], -MAX, 0, 2, p ) && isValidInt( v[1], 0, MAX, 2, p ) ) {\n TO_EXP_NEG = v[0] | 0;\n TO_EXP_POS = v[1] | 0;\n }\n } else if ( isValidInt( v, -MAX, MAX, 2, p ) ) {\n TO_EXP_NEG = -( TO_EXP_POS = ( v < 0 ? -v : v ) | 0 );\n }\n }\n r[p] = [ TO_EXP_NEG, TO_EXP_POS ];\n\n // RANGE {number|number[]} Non-zero integer, -MAX to MAX inclusive or\n // [integer -MAX to -1 inclusive, integer 1 to MAX inclusive].\n // 'config() RANGE not an integer: {v}'\n // 'config() RANGE cannot be zero: {v}'\n // 'config() RANGE out of range: {v}'\n if ( has( p = 'RANGE' ) ) {\n\n if ( isArray(v) ) {\n if ( isValidInt( v[0], -MAX, -1, 2, p ) && isValidInt( v[1], 1, MAX, 2, p ) ) {\n MIN_EXP = v[0] | 0;\n MAX_EXP = v[1] | 0;\n }\n } else if ( isValidInt( v, -MAX, MAX, 2, p ) ) {\n if ( v | 0 ) MIN_EXP = -( MAX_EXP = ( v < 0 ? -v : v ) | 0 );\n else if (ERRORS) raise( 2, p + ' cannot be zero', v );\n }\n }\n r[p] = [ MIN_EXP, MAX_EXP ];\n\n // ERRORS {boolean|number} true, false, 1 or 0.\n // 'config() ERRORS not a boolean or binary digit: {v}'\n if ( has( p = 'ERRORS' ) ) {\n\n if ( v === !!v || v === 1 || v === 0 ) {\n id = 0;\n isValidInt = ( ERRORS = !!v ) ? intValidatorWithErrors : intValidatorNoErrors;\n } else if (ERRORS) {\n raise( 2, p + notBool, v );\n }\n }\n r[p] = ERRORS;\n\n // CRYPTO {boolean|number} true, false, 1 or 0.\n // 'config() CRYPTO not a boolean or binary digit: {v}'\n // 'config() crypto unavailable: {crypto}'\n if ( has( p = 'CRYPTO' ) ) {\n\n if ( v === !!v || v === 1 || v === 0 ) {\n CRYPTO = !!( v && crypto && typeof crypto == 'object' );\n if ( v && !CRYPTO && ERRORS ) raise( 2, 'crypto unavailable', crypto );\n } else if (ERRORS) {\n raise( 2, p + notBool, v );\n }\n }\n r[p] = CRYPTO;\n\n // MODULO_MODE {number} Integer, 0 to 9 inclusive.\n // 'config() MODULO_MODE not an integer: {v}'\n // 'config() MODULO_MODE out of range: {v}'\n if ( has( p = 'MODULO_MODE' ) && isValidInt( v, 0, 9, 2, p ) ) {\n MODULO_MODE = v | 0;\n }\n r[p] = MODULO_MODE;\n\n // POW_PRECISION {number} Integer, 0 to MAX inclusive.\n // 'config() POW_PRECISION not an integer: {v}'\n // 'config() POW_PRECISION out of range: {v}'\n if ( has( p = 'POW_PRECISION' ) && isValidInt( v, 0, MAX, 2, p ) ) {\n POW_PRECISION = v | 0;\n }\n r[p] = POW_PRECISION;\n\n // FORMAT {object}\n // 'config() FORMAT not an object: {v}'\n if ( has( p = 'FORMAT' ) ) {\n\n if ( typeof v == 'object' ) {\n FORMAT = v;\n } else if (ERRORS) {\n raise( 2, p + ' not an object', v );\n }\n }\n r[p] = FORMAT;\n\n return r;\n };\n\n\n /*\n * Return a new BigNumber whose value is the maximum of the arguments.\n *\n * arguments {number|string|BigNumber}\n */\n BigNumber.max = function () { return maxOrMin( arguments, P.lt ); };\n\n\n /*\n * Return a new BigNumber whose value is the minimum of the arguments.\n *\n * arguments {number|string|BigNumber}\n */\n BigNumber.min = function () { return maxOrMin( arguments, P.gt ); };\n\n\n /*\n * Return a new BigNumber with a random value equal to or greater than 0 and less than 1,\n * and with dp, or DECIMAL_PLACES if dp is omitted, decimal places (or less if trailing\n * zeros are produced).\n *\n * [dp] {number} Decimal places. Integer, 0 to MAX inclusive.\n *\n * 'random() decimal places not an integer: {dp}'\n * 'random() decimal places out of range: {dp}'\n * 'random() crypto unavailable: {crypto}'\n */\n BigNumber.random = (function () {\n var pow2_53 = 0x20000000000000;\n\n // Return a 53 bit integer n, where 0 <= n < 9007199254740992.\n // Check if Math.random() produces more than 32 bits of randomness.\n // If it does, assume at least 53 bits are produced, otherwise assume at least 30 bits.\n // 0x40000000 is 2^30, 0x800000 is 2^23, 0x1fffff is 2^21 - 1.\n var random53bitInt = (Math.random() * pow2_53) & 0x1fffff\n ? function () { return mathfloor( Math.random() * pow2_53 ); }\n : function () { return ((Math.random() * 0x40000000 | 0) * 0x800000) +\n (Math.random() * 0x800000 | 0); };\n\n return function (dp) {\n var a, b, e, k, v,\n i = 0,\n c = [],\n rand = new BigNumber(ONE);\n\n dp = dp == null || !isValidInt( dp, 0, MAX, 14 ) ? DECIMAL_PLACES : dp | 0;\n k = mathceil( dp / LOG_BASE );\n\n if (CRYPTO) {\n\n // Browsers supporting crypto.getRandomValues.\n if ( crypto && crypto.getRandomValues ) {\n\n a = crypto.getRandomValues( new Uint32Array( k *= 2 ) );\n\n for ( ; i < k; ) {\n\n // 53 bits:\n // ((Math.pow(2, 32) - 1) * Math.pow(2, 21)).toString(2)\n // 11111 11111111 11111111 11111111 11100000 00000000 00000000\n // ((Math.pow(2, 32) - 1) >>> 11).toString(2)\n // 11111 11111111 11111111\n // 0x20000 is 2^21.\n v = a[i] * 0x20000 + (a[i + 1] >>> 11);\n\n // Rejection sampling:\n // 0 <= v < 9007199254740992\n // Probability that v >= 9e15, is\n // 7199254740992 / 9007199254740992 ~= 0.0008, i.e. 1 in 1251\n if ( v >= 9e15 ) {\n b = crypto.getRandomValues( new Uint32Array(2) );\n a[i] = b[0];\n a[i + 1] = b[1];\n } else {\n\n // 0 <= v <= 8999999999999999\n // 0 <= (v % 1e14) <= 99999999999999\n c.push( v % 1e14 );\n i += 2;\n }\n }\n i = k / 2;\n\n // Node.js supporting crypto.randomBytes.\n } else if ( crypto && crypto.randomBytes ) {\n\n // buffer\n a = crypto.randomBytes( k *= 7 );\n\n for ( ; i < k; ) {\n\n // 0x1000000000000 is 2^48, 0x10000000000 is 2^40\n // 0x100000000 is 2^32, 0x1000000 is 2^24\n // 11111 11111111 11111111 11111111 11111111 11111111 11111111\n // 0 <= v < 9007199254740992\n v = ( ( a[i] & 31 ) * 0x1000000000000 ) + ( a[i + 1] * 0x10000000000 ) +\n ( a[i + 2] * 0x100000000 ) + ( a[i + 3] * 0x1000000 ) +\n ( a[i + 4] << 16 ) + ( a[i + 5] << 8 ) + a[i + 6];\n\n if ( v >= 9e15 ) {\n crypto.randomBytes(7).copy( a, i );\n } else {\n\n // 0 <= (v % 1e14) <= 99999999999999\n c.push( v % 1e14 );\n i += 7;\n }\n }\n i = k / 7;\n } else if (ERRORS) {\n raise( 14, 'crypto unavailable', crypto );\n }\n }\n\n // Use Math.random: CRYPTO is false or crypto is unavailable and ERRORS is false.\n if (!i) {\n\n for ( ; i < k; ) {\n v = random53bitInt();\n if ( v < 9e15 ) c[i++] = v % 1e14;\n }\n }\n\n k = c[--i];\n dp %= LOG_BASE;\n\n // Convert trailing digits to zeros according to dp.\n if ( k && dp ) {\n v = POWS_TEN[LOG_BASE - dp];\n c[i] = mathfloor( k / v ) * v;\n }\n\n // Remove trailing elements which are zero.\n for ( ; c[i] === 0; c.pop(), i-- );\n\n // Zero?\n if ( i < 0 ) {\n c = [ e = 0 ];\n } else {\n\n // Remove leading elements which are zero and adjust exponent accordingly.\n for ( e = -1 ; c[0] === 0; c.shift(), e -= LOG_BASE);\n\n // Count the digits of the first element of c to determine leading zeros, and...\n for ( i = 1, v = c[0]; v >= 10; v /= 10, i++);\n\n // adjust the exponent accordingly.\n if ( i < LOG_BASE ) e -= LOG_BASE - i;\n }\n\n rand.e = e;\n rand.c = c;\n return rand;\n };\n })();\n\n\n // PRIVATE FUNCTIONS\n\n\n // Convert a numeric string of baseIn to a numeric string of baseOut.\n function convertBase( str, baseOut, baseIn, sign ) {\n var d, e, k, r, x, xc, y,\n i = str.indexOf( '.' ),\n dp = DECIMAL_PLACES,\n rm = ROUNDING_MODE;\n\n if ( baseIn < 37 ) str = str.toLowerCase();\n\n // Non-integer.\n if ( i >= 0 ) {\n k = POW_PRECISION;\n\n // Unlimited precision.\n POW_PRECISION = 0;\n str = str.replace( '.', '' );\n y = new BigNumber(baseIn);\n x = y.pow( str.length - i );\n POW_PRECISION = k;\n\n // Convert str as if an integer, then restore the fraction part by dividing the\n // result by its base raised to a power.\n y.c = toBaseOut( toFixedPoint( coeffToString( x.c ), x.e ), 10, baseOut );\n y.e = y.c.length;\n }\n\n // Convert the number as integer.\n xc = toBaseOut( str, baseIn, baseOut );\n e = k = xc.length;\n\n // Remove trailing zeros.\n for ( ; xc[--k] == 0; xc.pop() );\n if ( !xc[0] ) return '0';\n\n if ( i < 0 ) {\n --e;\n } else {\n x.c = xc;\n x.e = e;\n\n // sign is needed for correct rounding.\n x.s = sign;\n x = div( x, y, dp, rm, baseOut );\n xc = x.c;\n r = x.r;\n e = x.e;\n }\n\n d = e + dp + 1;\n\n // The rounding digit, i.e. the digit to the right of the digit that may be rounded up.\n i = xc[d];\n k = baseOut / 2;\n r = r || d < 0 || xc[d + 1] != null;\n\n r = rm < 4 ? ( i != null || r ) && ( rm == 0 || rm == ( x.s < 0 ? 3 : 2 ) )\n : i > k || i == k &&( rm == 4 || r || rm == 6 && xc[d - 1] & 1 ||\n rm == ( x.s < 0 ? 8 : 7 ) );\n\n if ( d < 1 || !xc[0] ) {\n\n // 1^-dp or 0.\n str = r ? toFixedPoint( '1', -dp ) : '0';\n } else {\n xc.length = d;\n\n if (r) {\n\n // Rounding up may mean the previous digit has to be rounded up and so on.\n for ( --baseOut; ++xc[--d] > baseOut; ) {\n xc[d] = 0;\n\n if ( !d ) {\n ++e;\n xc.unshift(1);\n }\n }\n }\n\n // Determine trailing zeros.\n for ( k = xc.length; !xc[--k]; );\n\n // E.g. [4, 11, 15] becomes 4bf.\n for ( i = 0, str = ''; i <= k; str += ALPHABET.charAt( xc[i++] ) );\n str = toFixedPoint( str, e );\n }\n\n // The caller will add the sign.\n return str;\n }\n\n\n // Perform division in the specified base. Called by div and convertBase.\n div = (function () {\n\n // Assume non-zero x and k.\n function multiply( x, k, base ) {\n var m, temp, xlo, xhi,\n carry = 0,\n i = x.length,\n klo = k % SQRT_BASE,\n khi = k / SQRT_BASE | 0;\n\n for ( x = x.slice(); i--; ) {\n xlo = x[i] % SQRT_BASE;\n xhi = x[i] / SQRT_BASE | 0;\n m = khi * xlo + xhi * klo;\n temp = klo * xlo + ( ( m % SQRT_BASE ) * SQRT_BASE ) + carry;\n carry = ( temp / base | 0 ) + ( m / SQRT_BASE | 0 ) + khi * xhi;\n x[i] = temp % base;\n }\n\n if (carry) x.unshift(carry);\n\n return x;\n }\n\n function compare( a, b, aL, bL ) {\n var i, cmp;\n\n if ( aL != bL ) {\n cmp = aL > bL ? 1 : -1;\n } else {\n\n for ( i = cmp = 0; i < aL; i++ ) {\n\n if ( a[i] != b[i] ) {\n cmp = a[i] > b[i] ? 1 : -1;\n break;\n }\n }\n }\n return cmp;\n }\n\n function subtract( a, b, aL, base ) {\n var i = 0;\n\n // Subtract b from a.\n for ( ; aL--; ) {\n a[aL] -= i;\n i = a[aL] < b[aL] ? 1 : 0;\n a[aL] = i * base + a[aL] - b[aL];\n }\n\n // Remove leading zeros.\n for ( ; !a[0] && a.length > 1; a.shift() );\n }\n\n // x: dividend, y: divisor.\n return function ( x, y, dp, rm, base ) {\n var cmp, e, i, more, n, prod, prodL, q, qc, rem, remL, rem0, xi, xL, yc0,\n yL, yz,\n s = x.s == y.s ? 1 : -1,\n xc = x.c,\n yc = y.c;\n\n // Either NaN, Infinity or 0?\n if ( !xc || !xc[0] || !yc || !yc[0] ) {\n\n return new BigNumber(\n\n // Return NaN if either NaN, or both Infinity or 0.\n !x.s || !y.s || ( xc ? yc && xc[0] == yc[0] : !yc ) ? NaN :\n\n // Return ±0 if x is ±0 or y is ±Infinity, or return ±Infinity as y is ±0.\n xc && xc[0] == 0 || !yc ? s * 0 : s / 0\n );\n }\n\n q = new BigNumber(s);\n qc = q.c = [];\n e = x.e - y.e;\n s = dp + e + 1;\n\n if ( !base ) {\n base = BASE;\n e = bitFloor( x.e / LOG_BASE ) - bitFloor( y.e / LOG_BASE );\n s = s / LOG_BASE | 0;\n }\n\n // Result exponent may be one less then the current value of e.\n // The coefficients of the BigNumbers from convertBase may have trailing zeros.\n for ( i = 0; yc[i] == ( xc[i] || 0 ); i++ );\n if ( yc[i] > ( xc[i] || 0 ) ) e--;\n\n if ( s < 0 ) {\n qc.push(1);\n more = true;\n } else {\n xL = xc.length;\n yL = yc.length;\n i = 0;\n s += 2;\n\n // Normalise xc and yc so highest order digit of yc is >= base / 2.\n\n n = mathfloor( base / ( yc[0] + 1 ) );\n\n // Not necessary, but to handle odd bases where yc[0] == ( base / 2 ) - 1.\n // if ( n > 1 || n++ == 1 && yc[0] < base / 2 ) {\n if ( n > 1 ) {\n yc = multiply( yc, n, base );\n xc = multiply( xc, n, base );\n yL = yc.length;\n xL = xc.length;\n }\n\n xi = yL;\n rem = xc.slice( 0, yL );\n remL = rem.length;\n\n // Add zeros to make remainder as long as divisor.\n for ( ; remL < yL; rem[remL++] = 0 );\n yz = yc.slice();\n yz.unshift(0);\n yc0 = yc[0];\n if ( yc[1] >= base / 2 ) yc0++;\n // Not necessary, but to prevent trial digit n > base, when using base 3.\n // else if ( base == 3 && yc0 == 1 ) yc0 = 1 + 1e-15;\n\n do {\n n = 0;\n\n // Compare divisor and remainder.\n cmp = compare( yc, rem, yL, remL );\n\n // If divisor < remainder.\n if ( cmp < 0 ) {\n\n // Calculate trial digit, n.\n\n rem0 = rem[0];\n if ( yL != remL ) rem0 = rem0 * base + ( rem[1] || 0 );\n\n // n is how many times the divisor goes into the current remainder.\n n = mathfloor( rem0 / yc0 );\n\n // Algorithm:\n // 1. product = divisor * trial digit (n)\n // 2. if product > remainder: product -= divisor, n--\n // 3. remainder -= product\n // 4. if product was < remainder at 2:\n // 5. compare new remainder and divisor\n // 6. If remainder > divisor: remainder -= divisor, n++\n\n if ( n > 1 ) {\n\n // n may be > base only when base is 3.\n if (n >= base) n = base - 1;\n\n // product = divisor * trial digit.\n prod = multiply( yc, n, base );\n prodL = prod.length;\n remL = rem.length;\n\n // Compare product and remainder.\n // If product > remainder.\n // Trial digit n too high.\n // n is 1 too high about 5% of the time, and is not known to have\n // ever been more than 1 too high.\n while ( compare( prod, rem, prodL, remL ) == 1 ) {\n n--;\n\n // Subtract divisor from product.\n subtract( prod, yL < prodL ? yz : yc, prodL, base );\n prodL = prod.length;\n cmp = 1;\n }\n } else {\n\n // n is 0 or 1, cmp is -1.\n // If n is 0, there is no need to compare yc and rem again below,\n // so change cmp to 1 to avoid it.\n // If n is 1, leave cmp as -1, so yc and rem are compared again.\n if ( n == 0 ) {\n\n // divisor < remainder, so n must be at least 1.\n cmp = n = 1;\n }\n\n // product = divisor\n prod = yc.slice();\n prodL = prod.length;\n }\n\n if ( prodL < remL ) prod.unshift(0);\n\n // Subtract product from remainder.\n subtract( rem, prod, remL, base );\n remL = rem.length;\n\n // If product was < remainder.\n if ( cmp == -1 ) {\n\n // Compare divisor and new remainder.\n // If divisor < new remainder, subtract divisor from remainder.\n // Trial digit n too low.\n // n is 1 too low about 5% of the time, and very rarely 2 too low.\n while ( compare( yc, rem, yL, remL ) < 1 ) {\n n++;\n\n // Subtract divisor from remainder.\n subtract( rem, yL < remL ? yz : yc, remL, base );\n remL = rem.length;\n }\n }\n } else if ( cmp === 0 ) {\n n++;\n rem = [0];\n } // else cmp === 1 and n will be 0\n\n // Add the next digit, n, to the result array.\n qc[i++] = n;\n\n // Update the remainder.\n if ( rem[0] ) {\n rem[remL++] = xc[xi] || 0;\n } else {\n rem = [ xc[xi] ];\n remL = 1;\n }\n } while ( ( xi++ < xL || rem[0] != null ) && s-- );\n\n more = rem[0] != null;\n\n // Leading zero?\n if ( !qc[0] ) qc.shift();\n }\n\n if ( base == BASE ) {\n\n // To calculate q.e, first get the number of digits of qc[0].\n for ( i = 1, s = qc[0]; s >= 10; s /= 10, i++ );\n round( q, dp + ( q.e = i + e * LOG_BASE - 1 ) + 1, rm, more );\n\n // Caller is convertBase.\n } else {\n q.e = e;\n q.r = +more;\n }\n\n return q;\n };\n })();\n\n\n /*\n * Return a string representing the value of BigNumber n in fixed-point or exponential\n * notation rounded to the specified decimal places or significant digits.\n *\n * n is a BigNumber.\n * i is the index of the last digit required (i.e. the digit that may be rounded up).\n * rm is the rounding mode.\n * caller is caller id: toExponential 19, toFixed 20, toFormat 21, toPrecision 24.\n */\n function format( n, i, rm, caller ) {\n var c0, e, ne, len, str;\n\n rm = rm != null && isValidInt( rm, 0, 8, caller, roundingMode )\n ? rm | 0 : ROUNDING_MODE;\n\n if ( !n.c ) return n.toString();\n c0 = n.c[0];\n ne = n.e;\n\n if ( i == null ) {\n str = coeffToString( n.c );\n str = caller == 19 || caller == 24 && ne <= TO_EXP_NEG\n ? toExponential( str, ne )\n : toFixedPoint( str, ne );\n } else {\n n = round( new BigNumber(n), i, rm );\n\n // n.e may have changed if the value was rounded up.\n e = n.e;\n\n str = coeffToString( n.c );\n len = str.length;\n\n // toPrecision returns exponential notation if the number of significant digits\n // specified is less than the number of digits necessary to represent the integer\n // part of the value in fixed-point notation.\n\n // Exponential notation.\n if ( caller == 19 || caller == 24 && ( i <= e || e <= TO_EXP_NEG ) ) {\n\n // Append zeros?\n for ( ; len < i; str += '0', len++ );\n str = toExponential( str, e );\n\n // Fixed-point notation.\n } else {\n i -= ne;\n str = toFixedPoint( str, e );\n\n // Append zeros?\n if ( e + 1 > len ) {\n if ( --i > 0 ) for ( str += '.'; i--; str += '0' );\n } else {\n i += e - len;\n if ( i > 0 ) {\n if ( e + 1 == len ) str += '.';\n for ( ; i--; str += '0' );\n }\n }\n }\n }\n\n return n.s < 0 && c0 ? '-' + str : str;\n }\n\n\n // Handle BigNumber.max and BigNumber.min.\n function maxOrMin( args, method ) {\n var m, n,\n i = 0;\n\n if ( isArray( args[0] ) ) args = args[0];\n m = new BigNumber( args[0] );\n\n for ( ; ++i < args.length; ) {\n n = new BigNumber( args[i] );\n\n // If any number is NaN, return NaN.\n if ( !n.s ) {\n m = n;\n break;\n } else if ( method.call( m, n ) ) {\n m = n;\n }\n }\n\n return m;\n }\n\n\n /*\n * Return true if n is an integer in range, otherwise throw.\n * Use for argument validation when ERRORS is true.\n */\n function intValidatorWithErrors( n, min, max, caller, name ) {\n if ( n < min || n > max || n != truncate(n) ) {\n raise( caller, ( name || 'decimal places' ) +\n ( n < min || n > max ? ' out of range' : ' not an integer' ), n );\n }\n\n return true;\n }\n\n\n /*\n * Strip trailing zeros, calculate base 10 exponent and check against MIN_EXP and MAX_EXP.\n * Called by minus, plus and times.\n */\n function normalise( n, c, e ) {\n var i = 1,\n j = c.length;\n\n // Remove trailing zeros.\n for ( ; !c[--j]; c.pop() );\n\n // Calculate the base 10 exponent. First get the number of digits of c[0].\n for ( j = c[0]; j >= 10; j /= 10, i++ );\n\n // Overflow?\n if ( ( e = i + e * LOG_BASE - 1 ) > MAX_EXP ) {\n\n // Infinity.\n n.c = n.e = null;\n\n // Underflow?\n } else if ( e < MIN_EXP ) {\n\n // Zero.\n n.c = [ n.e = 0 ];\n } else {\n n.e = e;\n n.c = c;\n }\n\n return n;\n }\n\n\n // Handle values that fail the validity test in BigNumber.\n parseNumeric = (function () {\n var basePrefix = /^(-?)0([xbo])/i,\n dotAfter = /^([^.]+)\\.$/,\n dotBefore = /^\\.([^.]+)$/,\n isInfinityOrNaN = /^-?(Infinity|NaN)$/,\n whitespaceOrPlus = /^\\s*\\+|^\\s+|\\s+$/g;\n\n return function ( x, str, num, b ) {\n var base,\n s = num ? str : str.replace( whitespaceOrPlus, '' );\n\n // No exception on ±Infinity or NaN.\n if ( isInfinityOrNaN.test(s) ) {\n x.s = isNaN(s) ? null : s < 0 ? -1 : 1;\n } else {\n if ( !num ) {\n\n // basePrefix = /^(-?)0([xbo])(?=\\w[\\w.]*$)/i\n s = s.replace( basePrefix, function ( m, p1, p2 ) {\n base = ( p2 = p2.toLowerCase() ) == 'x' ? 16 : p2 == 'b' ? 2 : 8;\n return !b || b == base ? p1 : m;\n });\n\n if (b) {\n base = b;\n\n // E.g. '1.' to '1', '.1' to '0.1'\n s = s.replace( dotAfter, '$1' ).replace( dotBefore, '0.$1' );\n }\n\n if ( str != s ) return new BigNumber( s, base );\n }\n\n // 'new BigNumber() not a number: {n}'\n // 'new BigNumber() not a base {b} number: {n}'\n if (ERRORS) raise( id, 'not a' + ( b ? ' base ' + b : '' ) + ' number', str );\n x.s = null;\n }\n\n x.c = x.e = null;\n id = 0;\n }\n })();\n\n\n // Throw a BigNumber Error.\n function raise( caller, msg, val ) {\n var error = new Error( [\n 'new BigNumber', // 0\n 'cmp', // 1\n 'config', // 2\n 'div', // 3\n 'divToInt', // 4\n 'eq', // 5\n 'gt', // 6\n 'gte', // 7\n 'lt', // 8\n 'lte', // 9\n 'minus', // 10\n 'mod', // 11\n 'plus', // 12\n 'precision', // 13\n 'random', // 14\n 'round', // 15\n 'shift', // 16\n 'times', // 17\n 'toDigits', // 18\n 'toExponential', // 19\n 'toFixed', // 20\n 'toFormat', // 21\n 'toFraction', // 22\n 'pow', // 23\n 'toPrecision', // 24\n 'toString', // 25\n 'BigNumber' // 26\n ][caller] + '() ' + msg + ': ' + val );\n\n error.name = 'BigNumber Error';\n id = 0;\n throw error;\n }\n\n\n /*\n * Round x to sd significant digits using rounding mode rm. Check for over/under-flow.\n * If r is truthy, it is known that there are more digits after the rounding digit.\n */\n function round( x, sd, rm, r ) {\n var d, i, j, k, n, ni, rd,\n xc = x.c,\n pows10 = POWS_TEN;\n\n // if x is not Infinity or NaN...\n if (xc) {\n\n // rd is the rounding digit, i.e. the digit after the digit that may be rounded up.\n // n is a base 1e14 number, the value of the element of array x.c containing rd.\n // ni is the index of n within x.c.\n // d is the number of digits of n.\n // i is the index of rd within n including leading zeros.\n // j is the actual index of rd within n (if < 0, rd is a leading zero).\n out: {\n\n // Get the number of digits of the first element of xc.\n for ( d = 1, k = xc[0]; k >= 10; k /= 10, d++ );\n i = sd - d;\n\n // If the rounding digit is in the first element of xc...\n if ( i < 0 ) {\n i += LOG_BASE;\n j = sd;\n n = xc[ ni = 0 ];\n\n // Get the rounding digit at index j of n.\n rd = n / pows10[ d - j - 1 ] % 10 | 0;\n } else {\n ni = mathceil( ( i + 1 ) / LOG_BASE );\n\n if ( ni >= xc.length ) {\n\n if (r) {\n\n // Needed by sqrt.\n for ( ; xc.length <= ni; xc.push(0) );\n n = rd = 0;\n d = 1;\n i %= LOG_BASE;\n j = i - LOG_BASE + 1;\n } else {\n break out;\n }\n } else {\n n = k = xc[ni];\n\n // Get the number of digits of n.\n for ( d = 1; k >= 10; k /= 10, d++ );\n\n // Get the index of rd within n.\n i %= LOG_BASE;\n\n // Get the index of rd within n, adjusted for leading zeros.\n // The number of leading zeros of n is given by LOG_BASE - d.\n j = i - LOG_BASE + d;\n\n // Get the rounding digit at index j of n.\n rd = j < 0 ? 0 : n / pows10[ d - j - 1 ] % 10 | 0;\n }\n }\n\n r = r || sd < 0 ||\n\n // Are there any non-zero digits after the rounding digit?\n // The expression n % pows10[ d - j - 1 ] returns all digits of n to the right\n // of the digit at j, e.g. if n is 908714 and j is 2, the expression gives 714.\n xc[ni + 1] != null || ( j < 0 ? n : n % pows10[ d - j - 1 ] );\n\n r = rm < 4\n ? ( rd || r ) && ( rm == 0 || rm == ( x.s < 0 ? 3 : 2 ) )\n : rd > 5 || rd == 5 && ( rm == 4 || r || rm == 6 &&\n\n // Check whether the digit to the left of the rounding digit is odd.\n ( ( i > 0 ? j > 0 ? n / pows10[ d - j ] : 0 : xc[ni - 1] ) % 10 ) & 1 ||\n rm == ( x.s < 0 ? 8 : 7 ) );\n\n if ( sd < 1 || !xc[0] ) {\n xc.length = 0;\n\n if (r) {\n\n // Convert sd to decimal places.\n sd -= x.e + 1;\n\n // 1, 0.1, 0.01, 0.001, 0.0001 etc.\n xc[0] = pows10[ sd % LOG_BASE ];\n x.e = -sd || 0;\n } else {\n\n // Zero.\n xc[0] = x.e = 0;\n }\n\n return x;\n }\n\n // Remove excess digits.\n if ( i == 0 ) {\n xc.length = ni;\n k = 1;\n ni--;\n } else {\n xc.length = ni + 1;\n k = pows10[ LOG_BASE - i ];\n\n // E.g. 56700 becomes 56000 if 7 is the rounding digit.\n // j > 0 means i > number of leading zeros of n.\n xc[ni] = j > 0 ? mathfloor( n / pows10[ d - j ] % pows10[j] ) * k : 0;\n }\n\n // Round up?\n if (r) {\n\n for ( ; ; ) {\n\n // If the digit to be rounded up is in the first element of xc...\n if ( ni == 0 ) {\n\n // i will be the length of xc[0] before k is added.\n for ( i = 1, j = xc[0]; j >= 10; j /= 10, i++ );\n j = xc[0] += k;\n for ( k = 1; j >= 10; j /= 10, k++ );\n\n // if i != k the length has increased.\n if ( i != k ) {\n x.e++;\n if ( xc[0] == BASE ) xc[0] = 1;\n }\n\n break;\n } else {\n xc[ni] += k;\n if ( xc[ni] != BASE ) break;\n xc[ni--] = 0;\n k = 1;\n }\n }\n }\n\n // Remove trailing zeros.\n for ( i = xc.length; xc[--i] === 0; xc.pop() );\n }\n\n // Overflow? Infinity.\n if ( x.e > MAX_EXP ) {\n x.c = x.e = null;\n\n // Underflow? Zero.\n } else if ( x.e < MIN_EXP ) {\n x.c = [ x.e = 0 ];\n }\n }\n\n return x;\n }\n\n\n // PROTOTYPE/INSTANCE METHODS\n\n\n /*\n * Return a new BigNumber whose value is the absolute value of this BigNumber.\n */\n P.absoluteValue = P.abs = function () {\n var x = new BigNumber(this);\n if ( x.s < 0 ) x.s = 1;\n return x;\n };\n\n\n /*\n * Return a new BigNumber whose value is the value of this BigNumber rounded to a whole\n * number in the direction of Infinity.\n */\n P.ceil = function () {\n return round( new BigNumber(this), this.e + 1, 2 );\n };\n\n\n /*\n * Return\n * 1 if the value of this BigNumber is greater than the value of BigNumber(y, b),\n * -1 if the value of this BigNumber is less than the value of BigNumber(y, b),\n * 0 if they have the same value,\n * or null if the value of either is NaN.\n */\n P.comparedTo = P.cmp = function ( y, b ) {\n id = 1;\n return compare( this, new BigNumber( y, b ) );\n };\n\n\n /*\n * Return the number of decimal places of the value of this BigNumber, or null if the value\n * of this BigNumber is ±Infinity or NaN.\n */\n P.decimalPlaces = P.dp = function () {\n var n, v,\n c = this.c;\n\n if ( !c ) return null;\n n = ( ( v = c.length - 1 ) - bitFloor( this.e / LOG_BASE ) ) * LOG_BASE;\n\n // Subtract the number of trailing zeros of the last number.\n if ( v = c[v] ) for ( ; v % 10 == 0; v /= 10, n-- );\n if ( n < 0 ) n = 0;\n\n return n;\n };\n\n\n /*\n * n / 0 = I\n * n / N = N\n * n / I = 0\n * 0 / n = 0\n * 0 / 0 = N\n * 0 / N = N\n * 0 / I = 0\n * N / n = N\n * N / 0 = N\n * N / N = N\n * N / I = N\n * I / n = I\n * I / 0 = I\n * I / N = N\n * I / I = N\n *\n * Return a new BigNumber whose value is the value of this BigNumber divided by the value of\n * BigNumber(y, b), rounded according to DECIMAL_PLACES and ROUNDING_MODE.\n */\n P.dividedBy = P.div = function ( y, b ) {\n id = 3;\n return div( this, new BigNumber( y, b ), DECIMAL_PLACES, ROUNDING_MODE );\n };\n\n\n /*\n * Return a new BigNumber whose value is the integer part of dividing the value of this\n * BigNumber by the value of BigNumber(y, b).\n */\n P.dividedToIntegerBy = P.divToInt = function ( y, b ) {\n id = 4;\n return div( this, new BigNumber( y, b ), 0, 1 );\n };\n\n\n /*\n * Return true if the value of this BigNumber is equal to the value of BigNumber(y, b),\n * otherwise returns false.\n */\n P.equals = P.eq = function ( y, b ) {\n id = 5;\n return compare( this, new BigNumber( y, b ) ) === 0;\n };\n\n\n /*\n * Return a new BigNumber whose value is the value of this BigNumber rounded to a whole\n * number in the direction of -Infinity.\n */\n P.floor = function () {\n return round( new BigNumber(this), this.e + 1, 3 );\n };\n\n\n /*\n * Return true if the value of this BigNumber is greater than the value of BigNumber(y, b),\n * otherwise returns false.\n */\n P.greaterThan = P.gt = function ( y, b ) {\n id = 6;\n return compare( this, new BigNumber( y, b ) ) > 0;\n };\n\n\n /*\n * Return true if the value of this BigNumber is greater than or equal to the value of\n * BigNumber(y, b), otherwise returns false.\n */\n P.greaterThanOrEqualTo = P.gte = function ( y, b ) {\n id = 7;\n return ( b = compare( this, new BigNumber( y, b ) ) ) === 1 || b === 0;\n\n };\n\n\n /*\n * Return true if the value of this BigNumber is a finite number, otherwise returns false.\n */\n P.isFinite = function () {\n return !!this.c;\n };\n\n\n /*\n * Return true if the value of this BigNumber is an integer, otherwise return false.\n */\n P.isInteger = P.isInt = function () {\n return !!this.c && bitFloor( this.e / LOG_BASE ) > this.c.length - 2;\n };\n\n\n /*\n * Return true if the value of this BigNumber is NaN, otherwise returns false.\n */\n P.isNaN = function () {\n return !this.s;\n };\n\n\n /*\n * Return true if the value of this BigNumber is negative, otherwise returns false.\n */\n P.isNegative = P.isNeg = function () {\n return this.s < 0;\n };\n\n\n /*\n * Return true if the value of this BigNumber is 0 or -0, otherwise returns false.\n */\n P.isZero = function () {\n return !!this.c && this.c[0] == 0;\n };\n\n\n /*\n * Return true if the value of this BigNumber is less than the value of BigNumber(y, b),\n * otherwise returns false.\n */\n P.lessThan = P.lt = function ( y, b ) {\n id = 8;\n return compare( this, new BigNumber( y, b ) ) < 0;\n };\n\n\n /*\n * Return true if the value of this BigNumber is less than or equal to the value of\n * BigNumber(y, b), otherwise returns false.\n */\n P.lessThanOrEqualTo = P.lte = function ( y, b ) {\n id = 9;\n return ( b = compare( this, new BigNumber( y, b ) ) ) === -1 || b === 0;\n };\n\n\n /*\n * n - 0 = n\n * n - N = N\n * n - I = -I\n * 0 - n = -n\n * 0 - 0 = 0\n * 0 - N = N\n * 0 - I = -I\n * N - n = N\n * N - 0 = N\n * N - N = N\n * N - I = N\n * I - n = I\n * I - 0 = I\n * I - N = N\n * I - I = N\n *\n * Return a new BigNumber whose value is the value of this BigNumber minus the value of\n * BigNumber(y, b).\n */\n P.minus = P.sub = function ( y, b ) {\n var i, j, t, xLTy,\n x = this,\n a = x.s;\n\n id = 10;\n y = new BigNumber( y, b );\n b = y.s;\n\n // Either NaN?\n if ( !a || !b ) return new BigNumber(NaN);\n\n // Signs differ?\n if ( a != b ) {\n y.s = -b;\n return x.plus(y);\n }\n\n var xe = x.e / LOG_BASE,\n ye = y.e / LOG_BASE,\n xc = x.c,\n yc = y.c;\n\n if ( !xe || !ye ) {\n\n // Either Infinity?\n if ( !xc || !yc ) return xc ? ( y.s = -b, y ) : new BigNumber( yc ? x : NaN );\n\n // Either zero?\n if ( !xc[0] || !yc[0] ) {\n\n // Return y if y is non-zero, x if x is non-zero, or zero if both are zero.\n return yc[0] ? ( y.s = -b, y ) : new BigNumber( xc[0] ? x :\n\n // IEEE 754 (2008) 6.3: n - n = -0 when rounding to -Infinity\n ROUNDING_MODE == 3 ? -0 : 0 );\n }\n }\n\n xe = bitFloor(xe);\n ye = bitFloor(ye);\n xc = xc.slice();\n\n // Determine which is the bigger number.\n if ( a = xe - ye ) {\n\n if ( xLTy = a < 0 ) {\n a = -a;\n t = xc;\n } else {\n ye = xe;\n t = yc;\n }\n\n t.reverse();\n\n // Prepend zeros to equalise exponents.\n for ( b = a; b--; t.push(0) );\n t.reverse();\n } else {\n\n // Exponents equal. Check digit by digit.\n j = ( xLTy = ( a = xc.length ) < ( b = yc.length ) ) ? a : b;\n\n for ( a = b = 0; b < j; b++ ) {\n\n if ( xc[b] != yc[b] ) {\n xLTy = xc[b] < yc[b];\n break;\n }\n }\n }\n\n // x < y? Point xc to the array of the bigger number.\n if (xLTy) t = xc, xc = yc, yc = t, y.s = -y.s;\n\n b = ( j = yc.length ) - ( i = xc.length );\n\n // Append zeros to xc if shorter.\n // No need to add zeros to yc if shorter as subtract only needs to start at yc.length.\n if ( b > 0 ) for ( ; b--; xc[i++] = 0 );\n b = BASE - 1;\n\n // Subtract yc from xc.\n for ( ; j > a; ) {\n\n if ( xc[--j] < yc[j] ) {\n for ( i = j; i && !xc[--i]; xc[i] = b );\n --xc[i];\n xc[j] += BASE;\n }\n\n xc[j] -= yc[j];\n }\n\n // Remove leading zeros and adjust exponent accordingly.\n for ( ; xc[0] == 0; xc.shift(), --ye );\n\n // Zero?\n if ( !xc[0] ) {\n\n // Following IEEE 754 (2008) 6.3,\n // n - n = +0 but n - n = -0 when rounding towards -Infinity.\n y.s = ROUNDING_MODE == 3 ? -1 : 1;\n y.c = [ y.e = 0 ];\n return y;\n }\n\n // No need to check for Infinity as +x - +y != Infinity && -x - -y != Infinity\n // for finite x and y.\n return normalise( y, xc, ye );\n };\n\n\n /*\n * n % 0 = N\n * n % N = N\n * n % I = n\n * 0 % n = 0\n * -0 % n = -0\n * 0 % 0 = N\n * 0 % N = N\n * 0 % I = 0\n * N % n = N\n * N % 0 = N\n * N % N = N\n * N % I = N\n * I % n = N\n * I % 0 = N\n * I % N = N\n * I % I = N\n *\n * Return a new BigNumber whose value is the value of this BigNumber modulo the value of\n * BigNumber(y, b). The result depends on the value of MODULO_MODE.\n */\n P.modulo = P.mod = function ( y, b ) {\n var q, s,\n x = this;\n\n id = 11;\n y = new BigNumber( y, b );\n\n // Return NaN if x is Infinity or NaN, or y is NaN or zero.\n if ( !x.c || !y.s || y.c && !y.c[0] ) {\n return new BigNumber(NaN);\n\n // Return x if y is Infinity or x is zero.\n } else if ( !y.c || x.c && !x.c[0] ) {\n return new BigNumber(x);\n }\n\n if ( MODULO_MODE == 9 ) {\n\n // Euclidian division: q = sign(y) * floor(x / abs(y))\n // r = x - qy where 0 <= r < abs(y)\n s = y.s;\n y.s = 1;\n q = div( x, y, 0, 3 );\n y.s = s;\n q.s *= s;\n } else {\n q = div( x, y, 0, MODULO_MODE );\n }\n\n return x.minus( q.times(y) );\n };\n\n\n /*\n * Return a new BigNumber whose value is the value of this BigNumber negated,\n * i.e. multiplied by -1.\n */\n P.negated = P.neg = function () {\n var x = new BigNumber(this);\n x.s = -x.s || null;\n return x;\n };\n\n\n /*\n * n + 0 = n\n * n + N = N\n * n + I = I\n * 0 + n = n\n * 0 + 0 = 0\n * 0 + N = N\n * 0 + I = I\n * N + n = N\n * N + 0 = N\n * N + N = N\n * N + I = N\n * I + n = I\n * I + 0 = I\n * I + N = N\n * I + I = I\n *\n * Return a new BigNumber whose value is the value of this BigNumber plus the value of\n * BigNumber(y, b).\n */\n P.plus = P.add = function ( y, b ) {\n var t,\n x = this,\n a = x.s;\n\n id = 12;\n y = new BigNumber( y, b );\n b = y.s;\n\n // Either NaN?\n if ( !a || !b ) return new BigNumber(NaN);\n\n // Signs differ?\n if ( a != b ) {\n y.s = -b;\n return x.minus(y);\n }\n\n var xe = x.e / LOG_BASE,\n ye = y.e / LOG_BASE,\n xc = x.c,\n yc = y.c;\n\n if ( !xe || !ye ) {\n\n // Return ±Infinity if either ±Infinity.\n if ( !xc || !yc ) return new BigNumber( a / 0 );\n\n // Either zero?\n // Return y if y is non-zero, x if x is non-zero, or zero if both are zero.\n if ( !xc[0] || !yc[0] ) return yc[0] ? y : new BigNumber( xc[0] ? x : a * 0 );\n }\n\n xe = bitFloor(xe);\n ye = bitFloor(ye);\n xc = xc.slice();\n\n // Prepend zeros to equalise exponents. Faster to use reverse then do unshifts.\n if ( a = xe - ye ) {\n if ( a > 0 ) {\n ye = xe;\n t = yc;\n } else {\n a = -a;\n t = xc;\n }\n\n t.reverse();\n for ( ; a--; t.push(0) );\n t.reverse();\n }\n\n a = xc.length;\n b = yc.length;\n\n // Point xc to the longer array, and b to the shorter length.\n if ( a - b < 0 ) t = yc, yc = xc, xc = t, b = a;\n\n // Only start adding at yc.length - 1 as the further digits of xc can be ignored.\n for ( a = 0; b; ) {\n a = ( xc[--b] = xc[b] + yc[b] + a ) / BASE | 0;\n xc[b] %= BASE;\n }\n\n if (a) {\n xc.unshift(a);\n ++ye;\n }\n\n // No need to check for zero, as +x + +y != 0 && -x + -y != 0\n // ye = MAX_EXP + 1 possible\n return normalise( y, xc, ye );\n };\n\n\n /*\n * Return the number of significant digits of the value of this BigNumber.\n *\n * [z] {boolean|number} Whether to count integer-part trailing zeros: true, false, 1 or 0.\n */\n P.precision = P.sd = function (z) {\n var n, v,\n x = this,\n c = x.c;\n\n // 'precision() argument not a boolean or binary digit: {z}'\n if ( z != null && z !== !!z && z !== 1 && z !== 0 ) {\n if (ERRORS) raise( 13, 'argument' + notBool, z );\n if ( z != !!z ) z = null;\n }\n\n if ( !c ) return null;\n v = c.length - 1;\n n = v * LOG_BASE + 1;\n\n if ( v = c[v] ) {\n\n // Subtract the number of trailing zeros of the last element.\n for ( ; v % 10 == 0; v /= 10, n-- );\n\n // Add the number of digits of the first element.\n for ( v = c[0]; v >= 10; v /= 10, n++ );\n }\n\n if ( z && x.e + 1 > n ) n = x.e + 1;\n\n return n;\n };\n\n\n /*\n * Return a new BigNumber whose value is the value of this BigNumber rounded to a maximum of\n * dp decimal places using rounding mode rm, or to 0 and ROUNDING_MODE respectively if\n * omitted.\n *\n * [dp] {number} Decimal places. Integer, 0 to MAX inclusive.\n * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.\n *\n * 'round() decimal places out of range: {dp}'\n * 'round() decimal places not an integer: {dp}'\n * 'round() rounding mode not an integer: {rm}'\n * 'round() rounding mode out of range: {rm}'\n */\n P.round = function ( dp, rm ) {\n var n = new BigNumber(this);\n\n if ( dp == null || isValidInt( dp, 0, MAX, 15 ) ) {\n round( n, ~~dp + this.e + 1, rm == null ||\n !isValidInt( rm, 0, 8, 15, roundingMode ) ? ROUNDING_MODE : rm | 0 );\n }\n\n return n;\n };\n\n\n /*\n * Return a new BigNumber whose value is the value of this BigNumber shifted by k places\n * (powers of 10). Shift to the right if n > 0, and to the left if n < 0.\n *\n * k {number} Integer, -MAX_SAFE_INTEGER to MAX_SAFE_INTEGER inclusive.\n *\n * If k is out of range and ERRORS is false, the result will be ±0 if k < 0, or ±Infinity\n * otherwise.\n *\n * 'shift() argument not an integer: {k}'\n * 'shift() argument out of range: {k}'\n */\n P.shift = function (k) {\n var n = this;\n return isValidInt( k, -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER, 16, 'argument' )\n\n // k < 1e+21, or truncate(k) will produce exponential notation.\n ? n.times( '1e' + truncate(k) )\n : new BigNumber( n.c && n.c[0] && ( k < -MAX_SAFE_INTEGER || k > MAX_SAFE_INTEGER )\n ? n.s * ( k < 0 ? 0 : 1 / 0 )\n : n );\n };\n\n\n /*\n * sqrt(-n) = N\n * sqrt( N) = N\n * sqrt(-I) = N\n * sqrt( I) = I\n * sqrt( 0) = 0\n * sqrt(-0) = -0\n *\n * Return a new BigNumber whose value is the square root of the value of this BigNumber,\n * rounded according to DECIMAL_PLACES and ROUNDING_MODE.\n */\n P.squareRoot = P.sqrt = function () {\n var m, n, r, rep, t,\n x = this,\n c = x.c,\n s = x.s,\n e = x.e,\n dp = DECIMAL_PLACES + 4,\n half = new BigNumber('0.5');\n\n // Negative/NaN/Infinity/zero?\n if ( s !== 1 || !c || !c[0] ) {\n return new BigNumber( !s || s < 0 && ( !c || c[0] ) ? NaN : c ? x : 1 / 0 );\n }\n\n // Initial estimate.\n s = Math.sqrt( +x );\n\n // Math.sqrt underflow/overflow?\n // Pass x to Math.sqrt as integer, then adjust the exponent of the result.\n if ( s == 0 || s == 1 / 0 ) {\n n = coeffToString(c);\n if ( ( n.length + e ) % 2 == 0 ) n += '0';\n s = Math.sqrt(n);\n e = bitFloor( ( e + 1 ) / 2 ) - ( e < 0 || e % 2 );\n\n if ( s == 1 / 0 ) {\n n = '1e' + e;\n } else {\n n = s.toExponential();\n n = n.slice( 0, n.indexOf('e') + 1 ) + e;\n }\n\n r = new BigNumber(n);\n } else {\n r = new BigNumber( s + '' );\n }\n\n // Check for zero.\n // r could be zero if MIN_EXP is changed after the this value was created.\n // This would cause a division by zero (x/t) and hence Infinity below, which would cause\n // coeffToString to throw.\n if ( r.c[0] ) {\n e = r.e;\n s = e + dp;\n if ( s < 3 ) s = 0;\n\n // Newton-Raphson iteration.\n for ( ; ; ) {\n t = r;\n r = half.times( t.plus( div( x, t, dp, 1 ) ) );\n\n if ( coeffToString( t.c ).slice( 0, s ) === ( n =\n coeffToString( r.c ) ).slice( 0, s ) ) {\n\n // The exponent of r may here be one less than the final result exponent,\n // e.g 0.0009999 (e-4) --> 0.001 (e-3), so adjust s so the rounding digits\n // are indexed correctly.\n if ( r.e < e ) --s;\n n = n.slice( s - 3, s + 1 );\n\n // The 4th rounding digit may be in error by -1 so if the 4 rounding digits\n // are 9999 or 4999 (i.e. approaching a rounding boundary) continue the\n // iteration.\n if ( n == '9999' || !rep && n == '4999' ) {\n\n // On the first iteration only, check to see if rounding up gives the\n // exact result as the nines may infinitely repeat.\n if ( !rep ) {\n round( t, t.e + DECIMAL_PLACES + 2, 0 );\n\n if ( t.times(t).eq(x) ) {\n r = t;\n break;\n }\n }\n\n dp += 4;\n s += 4;\n rep = 1;\n } else {\n\n // If rounding digits are null, 0{0,4} or 50{0,3}, check for exact\n // result. If not, then there are further digits and m will be truthy.\n if ( !+n || !+n.slice(1) && n.charAt(0) == '5' ) {\n\n // Truncate to the first rounding digit.\n round( r, r.e + DECIMAL_PLACES + 2, 1 );\n m = !r.times(r).eq(x);\n }\n\n break;\n }\n }\n }\n }\n\n return round( r, r.e + DECIMAL_PLACES + 1, ROUNDING_MODE, m );\n };\n\n\n /*\n * n * 0 = 0\n * n * N = N\n * n * I = I\n * 0 * n = 0\n * 0 * 0 = 0\n * 0 * N = N\n * 0 * I = N\n * N * n = N\n * N * 0 = N\n * N * N = N\n * N * I = N\n * I * n = I\n * I * 0 = N\n * I * N = N\n * I * I = I\n *\n * Return a new BigNumber whose value is the value of this BigNumber times the value of\n * BigNumber(y, b).\n */\n P.times = P.mul = function ( y, b ) {\n var c, e, i, j, k, m, xcL, xlo, xhi, ycL, ylo, yhi, zc,\n base, sqrtBase,\n x = this,\n xc = x.c,\n yc = ( id = 17, y = new BigNumber( y, b ) ).c;\n\n // Either NaN, ±Infinity or ±0?\n if ( !xc || !yc || !xc[0] || !yc[0] ) {\n\n // Return NaN if either is NaN, or one is 0 and the other is Infinity.\n if ( !x.s || !y.s || xc && !xc[0] && !yc || yc && !yc[0] && !xc ) {\n y.c = y.e = y.s = null;\n } else {\n y.s *= x.s;\n\n // Return ±Infinity if either is ±Infinity.\n if ( !xc || !yc ) {\n y.c = y.e = null;\n\n // Return ±0 if either is ±0.\n } else {\n y.c = [0];\n y.e = 0;\n }\n }\n\n return y;\n }\n\n e = bitFloor( x.e / LOG_BASE ) + bitFloor( y.e / LOG_BASE );\n y.s *= x.s;\n xcL = xc.length;\n ycL = yc.length;\n\n // Ensure xc points to longer array and xcL to its length.\n if ( xcL < ycL ) zc = xc, xc = yc, yc = zc, i = xcL, xcL = ycL, ycL = i;\n\n // Initialise the result array with zeros.\n for ( i = xcL + ycL, zc = []; i--; zc.push(0) );\n\n base = BASE;\n sqrtBase = SQRT_BASE;\n\n for ( i = ycL; --i >= 0; ) {\n c = 0;\n ylo = yc[i] % sqrtBase;\n yhi = yc[i] / sqrtBase | 0;\n\n for ( k = xcL, j = i + k; j > i; ) {\n xlo = xc[--k] % sqrtBase;\n xhi = xc[k] / sqrtBase | 0;\n m = yhi * xlo + xhi * ylo;\n xlo = ylo * xlo + ( ( m % sqrtBase ) * sqrtBase ) + zc[j] + c;\n c = ( xlo / base | 0 ) + ( m / sqrtBase | 0 ) + yhi * xhi;\n zc[j--] = xlo % base;\n }\n\n zc[j] = c;\n }\n\n if (c) {\n ++e;\n } else {\n zc.shift();\n }\n\n return normalise( y, zc, e );\n };\n\n\n /*\n * Return a new BigNumber whose value is the value of this BigNumber rounded to a maximum of\n * sd significant digits using rounding mode rm, or ROUNDING_MODE if rm is omitted.\n *\n * [sd] {number} Significant digits. Integer, 1 to MAX inclusive.\n * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.\n *\n * 'toDigits() precision out of range: {sd}'\n * 'toDigits() precision not an integer: {sd}'\n * 'toDigits() rounding mode not an integer: {rm}'\n * 'toDigits() rounding mode out of range: {rm}'\n */\n P.toDigits = function ( sd, rm ) {\n var n = new BigNumber(this);\n sd = sd == null || !isValidInt( sd, 1, MAX, 18, 'precision' ) ? null : sd | 0;\n rm = rm == null || !isValidInt( rm, 0, 8, 18, roundingMode ) ? ROUNDING_MODE : rm | 0;\n return sd ? round( n, sd, rm ) : n;\n };\n\n\n /*\n * Return a string representing the value of this BigNumber in exponential notation and\n * rounded using ROUNDING_MODE to dp fixed decimal places.\n *\n * [dp] {number} Decimal places. Integer, 0 to MAX inclusive.\n * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.\n *\n * 'toExponential() decimal places not an integer: {dp}'\n * 'toExponential() decimal places out of range: {dp}'\n * 'toExponential() rounding mode not an integer: {rm}'\n * 'toExponential() rounding mode out of range: {rm}'\n */\n P.toExponential = function ( dp, rm ) {\n return format( this,\n dp != null && isValidInt( dp, 0, MAX, 19 ) ? ~~dp + 1 : null, rm, 19 );\n };\n\n\n /*\n * Return a string representing the value of this BigNumber in fixed-point notation rounding\n * to dp fixed decimal places using rounding mode rm, or ROUNDING_MODE if rm is omitted.\n *\n * Note: as with JavaScript's number type, (-0).toFixed(0) is '0',\n * but e.g. (-0.00001).toFixed(0) is '-0'.\n *\n * [dp] {number} Decimal places. Integer, 0 to MAX inclusive.\n * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.\n *\n * 'toFixed() decimal places not an integer: {dp}'\n * 'toFixed() decimal places out of range: {dp}'\n * 'toFixed() rounding mode not an integer: {rm}'\n * 'toFixed() rounding mode out of range: {rm}'\n */\n P.toFixed = function ( dp, rm ) {\n return format( this, dp != null && isValidInt( dp, 0, MAX, 20 )\n ? ~~dp + this.e + 1 : null, rm, 20 );\n };\n\n\n /*\n * Return a string representing the value of this BigNumber in fixed-point notation rounded\n * using rm or ROUNDING_MODE to dp decimal places, and formatted according to the properties\n * of the FORMAT object (see BigNumber.config).\n *\n * FORMAT = {\n * decimalSeparator : '.',\n * groupSeparator : ',',\n * groupSize : 3,\n * secondaryGroupSize : 0,\n * fractionGroupSeparator : '\\xA0', // non-breaking space\n * fractionGroupSize : 0\n * };\n *\n * [dp] {number} Decimal places. Integer, 0 to MAX inclusive.\n * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.\n *\n * 'toFormat() decimal places not an integer: {dp}'\n * 'toFormat() decimal places out of range: {dp}'\n * 'toFormat() rounding mode not an integer: {rm}'\n * 'toFormat() rounding mode out of range: {rm}'\n */\n P.toFormat = function ( dp, rm ) {\n var str = format( this, dp != null && isValidInt( dp, 0, MAX, 21 )\n ? ~~dp + this.e + 1 : null, rm, 21 );\n\n if ( this.c ) {\n var i,\n arr = str.split('.'),\n g1 = +FORMAT.groupSize,\n g2 = +FORMAT.secondaryGroupSize,\n groupSeparator = FORMAT.groupSeparator,\n intPart = arr[0],\n fractionPart = arr[1],\n isNeg = this.s < 0,\n intDigits = isNeg ? intPart.slice(1) : intPart,\n len = intDigits.length;\n\n if (g2) i = g1, g1 = g2, g2 = i, len -= i;\n\n if ( g1 > 0 && len > 0 ) {\n i = len % g1 || g1;\n intPart = intDigits.substr( 0, i );\n\n for ( ; i < len; i += g1 ) {\n intPart += groupSeparator + intDigits.substr( i, g1 );\n }\n\n if ( g2 > 0 ) intPart += groupSeparator + intDigits.slice(i);\n if (isNeg) intPart = '-' + intPart;\n }\n\n str = fractionPart\n ? intPart + FORMAT.decimalSeparator + ( ( g2 = +FORMAT.fractionGroupSize )\n ? fractionPart.replace( new RegExp( '\\\\d{' + g2 + '}\\\\B', 'g' ),\n '$&' + FORMAT.fractionGroupSeparator )\n : fractionPart )\n : intPart;\n }\n\n return str;\n };\n\n\n /*\n * Return a string array representing the value of this BigNumber as a simple fraction with\n * an integer numerator and an integer denominator. The denominator will be a positive\n * non-zero value less than or equal to the specified maximum denominator. If a maximum\n * denominator is not specified, the denominator will be the lowest value necessary to\n * represent the number exactly.\n *\n * [md] {number|string|BigNumber} Integer >= 1 and < Infinity. The maximum denominator.\n *\n * 'toFraction() max denominator not an integer: {md}'\n * 'toFraction() max denominator out of range: {md}'\n */\n P.toFraction = function (md) {\n var arr, d0, d2, e, exp, n, n0, q, s,\n k = ERRORS,\n x = this,\n xc = x.c,\n d = new BigNumber(ONE),\n n1 = d0 = new BigNumber(ONE),\n d1 = n0 = new BigNumber(ONE);\n\n if ( md != null ) {\n ERRORS = false;\n n = new BigNumber(md);\n ERRORS = k;\n\n if ( !( k = n.isInt() ) || n.lt(ONE) ) {\n\n if (ERRORS) {\n raise( 22,\n 'max denominator ' + ( k ? 'out of range' : 'not an integer' ), md );\n }\n\n // ERRORS is false:\n // If md is a finite non-integer >= 1, round it to an integer and use it.\n md = !k && n.c && round( n, n.e + 1, 1 ).gte(ONE) ? n : null;\n }\n }\n\n if ( !xc ) return x.toString();\n s = coeffToString(xc);\n\n // Determine initial denominator.\n // d is a power of 10 and the minimum max denominator that specifies the value exactly.\n e = d.e = s.length - x.e - 1;\n d.c[0] = POWS_TEN[ ( exp = e % LOG_BASE ) < 0 ? LOG_BASE + exp : exp ];\n md = !md || n.cmp(d) > 0 ? ( e > 0 ? d : n1 ) : n;\n\n exp = MAX_EXP;\n MAX_EXP = 1 / 0;\n n = new BigNumber(s);\n\n // n0 = d1 = 0\n n0.c[0] = 0;\n\n for ( ; ; ) {\n q = div( n, d, 0, 1 );\n d2 = d0.plus( q.times(d1) );\n if ( d2.cmp(md) == 1 ) break;\n d0 = d1;\n d1 = d2;\n n1 = n0.plus( q.times( d2 = n1 ) );\n n0 = d2;\n d = n.minus( q.times( d2 = d ) );\n n = d2;\n }\n\n d2 = div( md.minus(d0), d1, 0, 1 );\n n0 = n0.plus( d2.times(n1) );\n d0 = d0.plus( d2.times(d1) );\n n0.s = n1.s = x.s;\n e *= 2;\n\n // Determine which fraction is closer to x, n0/d0 or n1/d1\n arr = div( n1, d1, e, ROUNDING_MODE ).minus(x).abs().cmp(\n div( n0, d0, e, ROUNDING_MODE ).minus(x).abs() ) < 1\n ? [ n1.toString(), d1.toString() ]\n : [ n0.toString(), d0.toString() ];\n\n MAX_EXP = exp;\n return arr;\n };\n\n\n /*\n * Return the value of this BigNumber converted to a number primitive.\n */\n P.toNumber = function () {\n var x = this;\n\n // Ensure zero has correct sign.\n return +x || ( x.s ? x.s * 0 : NaN );\n };\n\n\n /*\n * Return a BigNumber whose value is the value of this BigNumber raised to the power n.\n * If n is negative round according to DECIMAL_PLACES and ROUNDING_MODE.\n * If POW_PRECISION is not 0, round to POW_PRECISION using ROUNDING_MODE.\n *\n * n {number} Integer, -9007199254740992 to 9007199254740992 inclusive.\n * (Performs 54 loop iterations for n of 9007199254740992.)\n *\n * 'pow() exponent not an integer: {n}'\n * 'pow() exponent out of range: {n}'\n */\n P.toPower = P.pow = function (n) {\n var k, y,\n i = mathfloor( n < 0 ? -n : +n ),\n x = this;\n\n // Pass ±Infinity to Math.pow if exponent is out of range.\n if ( !isValidInt( n, -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER, 23, 'exponent' ) &&\n ( !isFinite(n) || i > MAX_SAFE_INTEGER && ( n /= 0 ) ||\n parseFloat(n) != n && !( n = NaN ) ) ) {\n return new BigNumber( Math.pow( +x, n ) );\n }\n\n // Truncating each coefficient array to a length of k after each multiplication equates\n // to truncating significant digits to POW_PRECISION + [28, 41], i.e. there will be a\n // minimum of 28 guard digits retained. (Using + 1.5 would give [9, 21] guard digits.)\n k = POW_PRECISION ? mathceil( POW_PRECISION / LOG_BASE + 2 ) : 0;\n y = new BigNumber(ONE);\n\n for ( ; ; ) {\n\n if ( i % 2 ) {\n y = y.times(x);\n if ( !y.c ) break;\n if ( k && y.c.length > k ) y.c.length = k;\n }\n\n i = mathfloor( i / 2 );\n if ( !i ) break;\n\n x = x.times(x);\n if ( k && x.c && x.c.length > k ) x.c.length = k;\n }\n\n if ( n < 0 ) y = ONE.div(y);\n return k ? round( y, POW_PRECISION, ROUNDING_MODE ) : y;\n };\n\n\n /*\n * Return a string representing the value of this BigNumber rounded to sd significant digits\n * using rounding mode rm or ROUNDING_MODE. If sd is less than the number of digits\n * necessary to represent the integer part of the value in fixed-point notation, then use\n * exponential notation.\n *\n * [sd] {number} Significant digits. Integer, 1 to MAX inclusive.\n * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.\n *\n * 'toPrecision() precision not an integer: {sd}'\n * 'toPrecision() precision out of range: {sd}'\n * 'toPrecision() rounding mode not an integer: {rm}'\n * 'toPrecision() rounding mode out of range: {rm}'\n */\n P.toPrecision = function ( sd, rm ) {\n return format( this, sd != null && isValidInt( sd, 1, MAX, 24, 'precision' )\n ? sd | 0 : null, rm, 24 );\n };\n\n\n /*\n * Return a string representing the value of this BigNumber in base b, or base 10 if b is\n * omitted. If a base is specified, including base 10, round according to DECIMAL_PLACES and\n * ROUNDING_MODE. If a base is not specified, and this BigNumber has a positive exponent\n * that is equal to or greater than TO_EXP_POS, or a negative exponent equal to or less than\n * TO_EXP_NEG, return exponential notation.\n *\n * [b] {number} Integer, 2 to 64 inclusive.\n *\n * 'toString() base not an integer: {b}'\n * 'toString() base out of range: {b}'\n */\n P.toString = function (b) {\n var str,\n n = this,\n s = n.s,\n e = n.e;\n\n // Infinity or NaN?\n if ( e === null ) {\n\n if (s) {\n str = 'Infinity';\n if ( s < 0 ) str = '-' + str;\n } else {\n str = 'NaN';\n }\n } else {\n str = coeffToString( n.c );\n\n if ( b == null || !isValidInt( b, 2, 64, 25, 'base' ) ) {\n str = e <= TO_EXP_NEG || e >= TO_EXP_POS\n ? toExponential( str, e )\n : toFixedPoint( str, e );\n } else {\n str = convertBase( toFixedPoint( str, e ), b | 0, 10, s );\n }\n\n if ( s < 0 && n.c[0] ) str = '-' + str;\n }\n\n return str;\n };\n\n\n /*\n * Return a new BigNumber whose value is the value of this BigNumber truncated to a whole\n * number.\n */\n P.truncated = P.trunc = function () {\n return round( new BigNumber(this), this.e + 1, 1 );\n };\n\n\n\n /*\n * Return as toString, but do not accept a base argument.\n */\n P.valueOf = P.toJSON = function () {\n return this.toString();\n };\n\n\n // Aliases for BigDecimal methods.\n //P.add = P.plus; // P.add included above\n //P.subtract = P.minus; // P.sub included above\n //P.multiply = P.times; // P.mul included above\n //P.divide = P.div;\n //P.remainder = P.mod;\n //P.compareTo = P.cmp;\n //P.negate = P.neg;\n\n\n if ( configObj != null ) BigNumber.config(configObj);\n\n return BigNumber;\n }\n\n\n // PRIVATE HELPER FUNCTIONS\n\n\n function bitFloor(n) {\n var i = n | 0;\n return n > 0 || n === i ? i : i - 1;\n }\n\n\n // Return a coefficient array as a string of base 10 digits.\n function coeffToString(a) {\n var s, z,\n i = 1,\n j = a.length,\n r = a[0] + '';\n\n for ( ; i < j; ) {\n s = a[i++] + '';\n z = LOG_BASE - s.length;\n for ( ; z--; s = '0' + s );\n r += s;\n }\n\n // Determine trailing zeros.\n for ( j = r.length; r.charCodeAt(--j) === 48; );\n return r.slice( 0, j + 1 || 1 );\n }\n\n\n // Compare the value of BigNumbers x and y.\n function compare( x, y ) {\n var a, b,\n xc = x.c,\n yc = y.c,\n i = x.s,\n j = y.s,\n k = x.e,\n l = y.e;\n\n // Either NaN?\n if ( !i || !j ) return null;\n\n a = xc && !xc[0];\n b = yc && !yc[0];\n\n // Either zero?\n if ( a || b ) return a ? b ? 0 : -j : i;\n\n // Signs differ?\n if ( i != j ) return i;\n\n a = i < 0;\n b = k == l;\n\n // Either Infinity?\n if ( !xc || !yc ) return b ? 0 : !xc ^ a ? 1 : -1;\n\n // Compare exponents.\n if ( !b ) return k > l ^ a ? 1 : -1;\n\n j = ( k = xc.length ) < ( l = yc.length ) ? k : l;\n\n // Compare digit by digit.\n for ( i = 0; i < j; i++ ) if ( xc[i] != yc[i] ) return xc[i] > yc[i] ^ a ? 1 : -1;\n\n // Compare lengths.\n return k == l ? 0 : k > l ^ a ? 1 : -1;\n }\n\n\n /*\n * Return true if n is a valid number in range, otherwise false.\n * Use for argument validation when ERRORS is false.\n * Note: parseInt('1e+1') == 1 but parseFloat('1e+1') == 10.\n */\n function intValidatorNoErrors( n, min, max ) {\n return ( n = truncate(n) ) >= min && n <= max;\n }\n\n\n function isArray(obj) {\n return Object.prototype.toString.call(obj) == '[object Array]';\n }\n\n\n /*\n * Convert string of baseIn to an array of numbers of baseOut.\n * Eg. convertBase('255', 10, 16) returns [15, 15].\n * Eg. convertBase('ff', 16, 10) returns [2, 5, 5].\n */\n function toBaseOut( str, baseIn, baseOut ) {\n var j,\n arr = [0],\n arrL,\n i = 0,\n len = str.length;\n\n for ( ; i < len; ) {\n for ( arrL = arr.length; arrL--; arr[arrL] *= baseIn );\n arr[ j = 0 ] += ALPHABET.indexOf( str.charAt( i++ ) );\n\n for ( ; j < arr.length; j++ ) {\n\n if ( arr[j] > baseOut - 1 ) {\n if ( arr[j + 1] == null ) arr[j + 1] = 0;\n arr[j + 1] += arr[j] / baseOut | 0;\n arr[j] %= baseOut;\n }\n }\n }\n\n return arr.reverse();\n }\n\n\n function toExponential( str, e ) {\n return ( str.length > 1 ? str.charAt(0) + '.' + str.slice(1) : str ) +\n ( e < 0 ? 'e' : 'e+' ) + e;\n }\n\n\n function toFixedPoint( str, e ) {\n var len, z;\n\n // Negative exponent?\n if ( e < 0 ) {\n\n // Prepend zeros.\n for ( z = '0.'; ++e; z += '0' );\n str = z + str;\n\n // Positive exponent\n } else {\n len = str.length;\n\n // Append zeros.\n if ( ++e > len ) {\n for ( z = '0', e -= len; --e; z += '0' );\n str += z;\n } else if ( e < len ) {\n str = str.slice( 0, e ) + '.' + str.slice(e);\n }\n }\n\n return str;\n }\n\n\n function truncate(n) {\n n = parseFloat(n);\n return n < 0 ? mathceil(n) : mathfloor(n);\n }\n\n\n // EXPORT\n\n\n BigNumber = another();\n\n // AMD.\n if ( typeof define == 'function' && define.amd ) {\n define( function () { return BigNumber; } );\n\n // Node and other environments that support module.exports.\n } else if ( typeof module != 'undefined' && module.exports ) {\n module.exports = BigNumber;\n if ( !crypto ) try { crypto = require('crypto'); } catch (e) {}\n\n // Browser.\n } else {\n global.BigNumber = BigNumber;\n }\n})(this);\n", - "var web3 = require('./lib/web3');\nweb3.providers.HttpProvider = require('./lib/web3/httpprovider');\nweb3.providers.QtSyncProvider = require('./lib/web3/qtsync');\nweb3.eth.contract = require('./lib/web3/contract');\nweb3.abi = require('./lib/solidity/abi');\n\n// dont override global variable\nif (typeof window !== 'undefined' && typeof window.web3 === 'undefined') {\n window.web3 = web3;\n}\n\nmodule.exports = web3;\n\n" + "var web3 = require('./lib/web3');\nweb3.providers.HttpProvider = require('./lib/web3/httpprovider');\nweb3.providers.QtSyncProvider = require('./lib/web3/qtsync');\nweb3.eth.contract = require('./lib/web3/contract');\n\n// dont override global variable\nif (typeof window !== 'undefined' && typeof window.web3 === 'undefined') {\n window.web3 = web3;\n}\n\nmodule.exports = web3;\n\n" ] } \ No newline at end of file diff --git a/dist/web3.min.js b/dist/web3.min.js index b02f1f966..eb4052b6c 100644 --- a/dist/web3.min.js +++ b/dist/web3.min.js @@ -1,2 +1,2 @@ -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 +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;ai;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":6,"./formatters":2,"./param":3,"bignumber.js":"bignumber.js"}],2:[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":5,"../utils/utils":6,"./param":3,"bignumber.js":"bignumber.js"}],3:[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":6}],4:[function(t,e,n){"use strict";n.XMLHttpRequest="undefined"==typeof XMLHttpRequest?{}:XMLHttpRequest},{}],5:[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"}],6:[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[t.length-1]),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.unpackOutput=function(t){if(null!==t){t=t.length>=2?t.slice(2):t;var e=o.decodeParams(this._outputTypes,t);return 1===e.length?e[0]:e}},a.prototype.call=function(){var t=Array.prototype.slice.call(arguments),e=this.extractCallback(t),n=this.toPayload(t);if(!e){var o=r.eth.call(n);return this.unpackOutput(o)}var i=this;r.eth.call(n,function(t,n){e(t,i.unpackOutput(n))})},a.prototype.sendTransaction=function(){var t=Array.prototype.slice.call(arguments),e=this.extractCallback(t),n=this.toPayload(t);return e?void r.eth.sendTransaction(n,e):void r.eth.sendTransaction(n)},a.prototype.displayName=function(){return i.extractDisplayName(this._name)},a.prototype.typeName=function(){return i.extractTypeName(this._name)},a.prototype.request=function(){var t=Array.prototype.slice.call(arguments),e=this.extractCallback(t),n=this.toPayload(t),r=this.unpackOutput.bind(this);return{callback:e,payload:n,format:r}},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.request=this.request.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":1,"../utils/utils":6,"../web3":8}],18:[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":12,xmlhttprequest:4}],19:[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},{}],20:[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():void 0},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.request=this.request.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.request=function(){var t=this.toPayload(Array.prototype.slice.call(arguments));return t.format=this.formatOutput.bind(this),t},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(n,e.formatOutput(r))})}return this.formatOutput(r.getInstance().send(t))},e.exports=a},{"../utils/utils":6,"./errors":12,"./requestmanager":24}],21:[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":6,"./property":22}],22:[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)},n=this.name.split("."),r=n[0];n.length>1&&(t[n[0]]=t[n[0]]||{},t=t[n[0]],r=n[1]),Object.defineProperty(t,r,e);var o=function(t,e){return t+e.charAt(0).toUpperCase()+e.slice(1)};t[o("get",r)]=this.getAsync.bind(this)},o.prototype.get=function(){return this.formatOutput(r.getInstance().send({method:this.getter}))},o.prototype.getAsync=function(t){var e=this;r.getInstance().sendAsync({method:this.getter},function(n,r){return n?t(n):void t(n,e.formatOutput(r))})},e.exports=o},{"./requestmanager":24}],23:[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},{}],24:[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.sendBatch=function(t,e){if(!this.provider)return e(a.InvalidProvider());var n=r.getInstance().toBatchPayload(t);this.provider.sendAsync(n,function(t,n){return t?e(t):o.isArray(n)?void e(t,n):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":5,"../utils/utils":6,"./errors":12,"./jsonrpc":19}],25:[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":16,"./method":20}],26:[function(t,e,n){var r=t("./method"),o=function(){var t=function(t){var e=t[0];switch(e){case"latest":return t.pop(),this.params=0,"eth_newBlockFilter";case"pending":return t.pop(),this.params=0,"eth_newPendingTransactionFilter";default:return"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":20}],27:[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 W&&D(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),S(l,L+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,W&&c.replace(/^0\.0*|\./,"").length>15&&D(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&&W&&u>15&&D(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=L,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&&J(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&&j>=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||j>=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))&&D(r,(o||"decimal places")+(e>t||t>n?" out of range":" not an integer"),t),!0}function k(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 D(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")&&J(t,0,P,2,e)&&(L=0|t),r[e]=L,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],-P,0,2,e)&&J(t[1],0,P,2,e)&&(j=0|t[0],H=0|t[1]):J(t,-P,P,2,e)&&(j=-(H=0|(0>t?-t:t)))),r[e]=[j,H],a(e="RANGE")&&(u(t)?J(t[0],-P,-1,2,e)&&J(t[1],1,P,2,e)&&(M=0|t[0],G=0|t[1]):J(t,-P,P,2,e)&&(0|t?M=-(G=0|(0>t?-t:t)):W&&D(2,e+" cannot be zero",t))),r[e]=[M,G],a(e="ERRORS")&&(t===!!t||1===t||0===t?(R=0,J=(W=!!t)?A:s):W&&D(2,e+b,t)),r[e]=W,a(e="CRYPTO")&&(t===!!t||1===t||0===t?(V=!(!t||!h||"object"!=typeof h),t&&!V&&W&&D(2,"crypto unavailable",h)):W&&D(2,e+b,t)),r[e]=V,a(e="MODULO_MODE")&&J(t,0,9,2,e)&&($=0|t),r[e]=$,a(e="POW_PRECISION")&&J(t,0,P,2,e)&&(z=0|t),r[e]=z,a(e="FORMAT")&&("object"==typeof t?X=t:W&&D(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(q);if(t=null!=t&&J(t,0,P,14)?0|t:L,a=y(t/I),V)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 W&&D(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,k=i.c,D=a.c;if(!(k&&k[0]&&D&&D[0]))return new e(i.s&&a.s&&(k?!D||k[0]!=D[0]:D)?k&&0==k[0]||!D?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;D[p]==(k[p]||0);p++);if(D[p]>(k[p]||0)&&f--,0>A)b.push(1),m=!0;else{for(O=k.length,P=D.length,p=0,A+=2,h=v(c/(D[0]+1)),h>1&&(D=t(D,h,c),k=t(k,h,c),P=D.length,O=k.length),N=P,w=k.slice(0,P),_=w.length;P>_;w[_++]=0);T=D.slice(),T.unshift(0),B=D[0],D[1]>=c/2&&B++;do{if(h=0,l=n(D,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(D,h,c),g=d.length,_=w.length;1==n(d,w,g,_);)h--,r(d,g>P?T:D,g,c),g=d.length,l=1;else 0==h&&(l=h=1),d=D.slice(),g=d.length;if(_>g&&d.unshift(0),r(w,d,_,c),_=w.length,-1==l)for(;n(D,w,P,_)<1;)h++,r(w,_>P?T:D,_,c),_=w.length}else 0===l&&(h++,w=[0]);b[p++]=h,w[0]?w[_++]=k[N]||0:(w=[k[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);W&&D(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),L,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),k(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&&(W&&D(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||J(t,0,P,15))&&S(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,-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=L+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(),k(t,g,i)},C.toDigits=function(t,n){var r=new e(this);return t=null!=t&&J(t,1,P,18,"precision")?0|t:null,n=null!=n&&J(n,0,8,18,w)?0|n:U,t?S(r,t,n):r},C.toExponential=function(t,e){return m(this,null!=t&&J(t,0,P,19)?~~t+1:null,e,19)},C.toFixed=function(t,e){return m(this,null!=t&&J(t,0,P,20)?~~t+this.e+1:null,e,20)},C.toFormat=function(t,e){var n=m(this,null!=t&&J(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=W,m=this,h=m.c,d=new e(q),g=r=new e(q),y=c=new e(q);if(null!=t&&(W=!1,u=new e(t),W=p,(!(p=u.isInt())||u.lt(q))&&(W&&D(22,"max denominator "+(p?"out of range":"not an integer"),t),t=!p&&u.c&&S(u,u.e+1,1).gte(q)?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(!J(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(q);;){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=q.div(r)),n?S(r,z,U):r},C.toPrecision=function(t,e){return m(this,null!=t&&J(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&&J(t,2,64,25,"base")?n(f(e,a),0|t,10,o):j>=a||a>=H?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:27}],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"),"undefined"!=typeof window&&"undefined"==typeof window.web3&&(window.web3=r),e.exports=r},{"./lib/web3":8,"./lib/web3/contract":10,"./lib/web3/httpprovider":18,"./lib/web3/qtsync":23}]},{},["web3"]); \ No newline at end of file diff --git a/example/contract.html b/example/contract.html index a32098536..3b83d37b1 100644 --- a/example/contract.html +++ b/example/contract.html @@ -8,14 +8,16 @@ var web3 = require('web3'); web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545")); - // solidity source code - /*var source = "" +*/ - /*"contract test {\n" +*/ - /*" function multiply(uint a) constant returns(uint d) {\n" +*/ - /*" return a * 7;\n" +*/ - /*" }\n" +*/ - /*"}\n";*/ - var source = "605280600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b60376004356041565b8060005260206000f35b6000600782029050604d565b91905056"; + // solidity code code + var source = "" + + "contract test {\n" + + " function multiply(uint a) constant returns(uint d) {\n" + + " return a * 7;\n" + + " }\n" + + "}\n"; + + var code = web3.eth.compile.solidity(source).code; + /*var code = "605280600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b60376004356041565b8060005260206000f35b6000600782029050604d565b91905056";*/ // contract description, this is autogenerated using solc CLI var desc = [{ @@ -37,15 +39,30 @@ function createExampleContract() { // hide create button document.getElementById('create').style.visibility = 'hidden'; - document.getElementById('source').innerText = source; + document.getElementById('code').innerText = code; // let's assume that coinbase is our account web3.eth.defaultAccount = web3.eth.coinbase; + var watch = web3.eth.filter('latest'); + // create contract - var Contract = web3.eth.contract(desc); - myContract = new Contract({data: source}); - document.getElementById('call').style.visibility = 'visible'; + myContract = web3.eth.contract(desc).new({data: code}); + console.log('address: ' + myContract.address); + document.getElementById('status').innerText = "transaction sent, waiting for confirmation"; + watch.watch(function (err, hash) { + var block = web3.eth.getBlock(hash, true); + var contractMined = block.transactions.reduce(function (mined, th) { + // TODO: compiled code do not have 0x prefix + return mined || (th.from === web3.eth.defaultAccount && th.input.indexOf(code) !== -1); + }, false); + + if (contractMined) { + document.getElementById('status').innerText = 'Mined!'; + document.getElementById('call').style.visibility = 'visible'; + } + }); + } function callExampleContract() { @@ -61,7 +78,8 @@

contract

-
+
+
diff --git a/example/event_inc.html b/example/event_inc.html index ac12c6447..16eaa046f 100644 --- a/example/event_inc.html +++ b/example/event_inc.html @@ -6,19 +6,20 @@ var web3 = require('web3'); web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')); - /*var source = "" + */ - /*"contract Contract { " +*/ - /*" event Incremented(bool indexed odd, uint x); " +*/ - /*" function Contract() { " +*/ - /*" x = 69; " +*/ - /*" } " +*/ - /*" function inc() { " +*/ - /*" ++x; " +*/ - /*" Incremented(x % 2 == 1, x); " +*/ - /*" } " +*/ - /*" uint x; " +*/ - /*"}";*/ - var source = "5b60456000600050819055505b608c8060196000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063371303c014602e57005b6034603a565b60006000f35b6000600081815054600101919050819055506001600260006000505406147f6e61ef44ac2747ff8b84d353a908eb8bd5c3fb118334d57698c5cfc7041196ad600060006000505481526020016000a25b56"; + var source = "" + + "contract Contract { " + + " event Incremented(bool indexed odd, uint x); " + + " function Contract() { " + + " x = 70; " + + " } " + + " function inc() { " + + " ++x; " + + " Incremented(x % 2 == 1, x); " + + " } " + + " uint x; " + + "}"; + var code = web3.eth.compile.solidity(source).code; + /*var code = "5b60456000600050819055505b608c8060196000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063371303c014602e57005b6034603a565b60006000f35b6000600081815054600101919050819055506001600260006000505406147f6e61ef44ac2747ff8b84d353a908eb8bd5c3fb118334d57698c5cfc7041196ad600060006000505481526020016000a25b56";*/ var desc = [{ "constant" : false, @@ -51,13 +52,40 @@ var createContract = function () { // let's assume that we have a private key to coinbase ;) web3.eth.defaultAccount = web3.eth.coinbase; - var Contract = web3.eth.contract(desc); - contract = new Contract({data: source}); + + var watch = web3.eth.filter('latest'); + + contract = web3.eth.contract(desc).new({data: code}); + + console.log('address: ' + contract.address); + + document.getElementById('create').style.visibility = 'hidden'; + document.getElementById('status').innerText = "transaction sent, waiting for confirmation"; + watch.watch(function (err, hash) { + var block = web3.eth.getBlock(hash, true); + var contractMined = block.transactions.reduce(function (mined, th) { + // TODO: compiled code do not have 0x prefix + return mined || (th.from === web3.eth.defaultAccount && th.input.indexOf(code) !== -1); + }, false); + + if (contractMined) { + document.getElementById('status').innerText = 'Mined!'; + document.getElementById('call').style.visibility = 'visible'; + } + }); + contract.Incremented({odd: true}).watch(update); }; + var counter = 0; var callContract = function () { + counter++; + var all = 70 + counter; + document.getElementById('count').innerText = 'Transaction sent ' + counter + ' times. ' + + 'Expected x value is: ' + (all - (all % 2 ? 0 : 1)) + ' ' + + 'Waiting for the blocks to be mined...'; + contract.inc(); }; @@ -66,12 +94,14 @@ +
- +
- +
+
diff --git a/example/node-app.js b/example/node-app.js index 72b3986da..909c9d275 100644 --- a/example/node-app.js +++ b/example/node-app.js @@ -2,11 +2,11 @@ var web3 = require("../index.js"); -web3.setProvider(new web3.providers.HttpProvider('http://localhost:8080')); +web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')); var coinbase = web3.eth.coinbase; console.log(coinbase); var balance = web3.eth.getBalance(coinbase); -console.log(balance); +console.log(balance.toString(10)); diff --git a/index.js b/index.js index ae231d7d9..7a1c06902 100644 --- a/index.js +++ b/index.js @@ -2,7 +2,6 @@ var web3 = require('./lib/web3'); web3.providers.HttpProvider = require('./lib/web3/httpprovider'); web3.providers.QtSyncProvider = require('./lib/web3/qtsync'); web3.eth.contract = require('./lib/web3/contract'); -web3.abi = require('./lib/solidity/abi'); // dont override global variable if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') { diff --git a/lib/solidity/abi.js b/lib/solidity/abi.js deleted file mode 100644 index feb139ed4..000000000 --- a/lib/solidity/abi.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - This file is part of ethereum.js. - - ethereum.js is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - ethereum.js 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with ethereum.js. If not, see . -*/ -/** - * @file abi.js - * @author Marek Kotewicz - * @author Gav Wood - * @date 2014 - */ - -var coder = require('./coder'); -var utils = require('./utils'); - -var formatConstructorParams = function (abi, params) { - 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 coder.encodeParams(constructor.inputs.map(function (input) { - return input.type; - }), params); -}; - -module.exports = { - formatConstructorParams: formatConstructorParams -}; - diff --git a/lib/solidity/utils.js b/lib/solidity/utils.js deleted file mode 100644 index 23566f74a..000000000 --- a/lib/solidity/utils.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - This file is part of ethereum.js. - - ethereum.js is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - ethereum.js 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with ethereum.js. If not, see . -*/ -/** - * @file utils.js - * @author Marek Kotewicz - * @date 2015 - */ - -/** - * Returns the contstructor with matching number of arguments - * - * @method getConstructor - * @param {Array} abi - * @param {Number} numberOfArgs - * @returns {Object} constructor function abi - */ -var getConstructor = function (abi, numberOfArgs) { - return abi.filter(function (f) { - return f.type === 'constructor' && f.inputs.length === numberOfArgs; - })[0]; -}; - -//var getSupremeType = function (type) { - //return type.substr(0, type.indexOf('[')) + ']'; -//}; - - -module.exports = { - getConstructor: getConstructor -}; - diff --git a/lib/utils/utils.js b/lib/utils/utils.js index baaaa7d48..91964c333 100644 --- a/lib/utils/utils.js +++ b/lib/utils/utils.js @@ -363,6 +363,7 @@ var toAddress = function (address) { return '0x' + padLeft(toHex(address).substr(2), 40); }; + /** * Returns true if object is BigNumber, otherwise false * diff --git a/lib/version.json b/lib/version.json index e5c97ebab..70753fc9d 100644 --- a/lib/version.json +++ b/lib/version.json @@ -1,3 +1,3 @@ { - "version": "0.3.6" + "version": "0.4.2" } diff --git a/lib/web3.js b/lib/web3.js index 47db94278..98460fea4 100644 --- a/lib/web3.js +++ b/lib/web3.js @@ -37,6 +37,7 @@ var RequestManager = require('./web3/requestmanager'); var c = require('./utils/config'); var Method = require('./web3/method'); var Property = require('./web3/property'); +var Batch = require('./web3/batch'); var web3Methods = [ new Method({ @@ -129,6 +130,9 @@ web3.toBigNumber = utils.toBigNumber; web3.toWei = utils.toWei; web3.fromWei = utils.fromWei; web3.isAddress = utils.isAddress; +web3.createBatch = function () { + return new Batch(); +}; // ADD defaultblock Object.defineProperty(web3.eth, 'defaultBlock', { diff --git a/lib/web3/batch.js b/lib/web3/batch.js new file mode 100644 index 000000000..ca32bf725 --- /dev/null +++ b/lib/web3/batch.js @@ -0,0 +1,61 @@ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see . +*/ +/** + * @file batch.js + * @author Marek Kotewicz + * @date 2015 + */ + +var RequestManager = require('./requestmanager'); + +var Batch = function () { + this.requests = []; +}; + +/** + * Should be called to add create new request to batch request + * + * @method add + * @param {Object} jsonrpc requet object + */ +Batch.prototype.add = function (request) { + this.requests.push(request); +}; + +/** + * Should be called to execute batch request + * + * @method execute + */ +Batch.prototype.execute = function () { + var requests = this.requests; + RequestManager.getInstance().sendBatch(requests, function (err, results) { + results = results || []; + requests.map(function (request, index) { + return results[index] || {}; + }).map(function (result, index) { + return requests[index].format ? requests[index].format(result.result) : result.result; + }).forEach(function (result, index) { + if (requests[index].callback) { + requests[index].callback(err, result); + } + }); + }); +}; + +module.exports = Batch; + diff --git a/lib/web3/contract.js b/lib/web3/contract.js index 47ffae8f4..9666f9eaa 100644 --- a/lib/web3/contract.js +++ b/lib/web3/contract.js @@ -21,13 +21,39 @@ */ var web3 = require('../web3'); -var solAbi = require('../solidity/abi'); var utils = require('../utils/utils'); +var coder = require('../solidity/coder'); var SolidityEvent = require('./event'); var SolidityFunction = require('./function'); -var addFunctionsToContract = function (contract, desc) { - desc.filter(function (json) { +/** + * Should be called to encode constructor params + * + * @method encodeConstructorParams + * @param {Array} abi + * @param {Array} constructor params + */ +var encodeConstructorParams = function (abi, params) { + return abi.filter(function (json) { + return json.type === 'constructor' && json.inputs.length === params.length; + }).map(function (json) { + return json.inputs.map(function (input) { + return input.type; + }); + }).map(function (types) { + return coder.encodeParams(types, params); + })[0] || ''; +}; + +/** + * Should be called to add functions to contract object + * + * @method addFunctionsToContract + * @param {Contract} contract + * @param {Array} abi + */ +var addFunctionsToContract = function (contract, abi) { + abi.filter(function (json) { return json.type === 'function'; }).map(function (json) { return new SolidityFunction(json, contract.address); @@ -36,8 +62,15 @@ var addFunctionsToContract = function (contract, desc) { }); }; -var addEventsToContract = function (contract, desc) { - desc.filter(function (json) { +/** + * Should be called to add events to contract object + * + * @method addEventsToContract + * @param {Contract} contract + * @param {Array} abi + */ +var addEventsToContract = function (contract, abi) { + abi.filter(function (json) { return json.type === 'event'; }).map(function (json) { return new SolidityEvent(json, contract.address); @@ -47,59 +80,100 @@ var addEventsToContract = function (contract, desc) { }; /** - * This method should be called when we want to call / transact some solidity method from javascript - * it returns an object which has same methods available as solidity contract description - * usage example: - * - * var abi = [{ - * name: 'myMethod', - * inputs: [{ name: 'a', type: 'string' }], - * outputs: [{name: 'd', type: 'string' }] - * }]; // contract abi - * - * var MyContract = web3.eth.contract(abi); // creation of contract prototype - * - * var contractInstance = new MyContract('0x0123123121'); + * Should be called to create new ContractFactory * - * contractInstance.myMethod('this is test string param for call'); // myMethod call (implicit, default) - * contractInstance.call().myMethod('this is test string param for call'); // myMethod call (explicit) - * contractInstance.sendTransaction().myMethod('this is test string param for transact'); // myMethod sendTransaction - * - * @param abi - abi json description of the contract, which is being created - * @returns contract object + * @method contract + * @param {Array} abi + * @returns {ContractFactory} new contract factory */ var contract = function (abi) { + return new ContractFactory(abi); +}; - // return prototype - return Contract.bind(null, abi); +/** + * Should be called to create new ContractFactory instance + * + * @method ContractFactory + * @param {Array} abi + */ +var ContractFactory = function (abi) { + this.abi = abi; }; -var Contract = function (abi, options) { - - this.address = ''; - if (utils.isAddress(options)) { - this.address = options; - } else { // is an object! - // TODO, parse the rest of the args - options = options || {}; - var args = Array.prototype.slice.call(arguments, 2); - var bytes = solAbi.formatConstructorParams(abi, args); - options.data += bytes; - this.address = web3.eth.sendTransaction(options); +/** + * Should be called to create new contract on a blockchain + * + * @method new + * @param {Any} contract constructor param1 (optional) + * @param {Any} contract constructor param2 (optional) + * @param {Object} contract transaction object (required) + * @param {Function} callback + * @returns {Contract} returns contract if no callback was passed, + * otherwise calls callback function (err, contract) + */ +ContractFactory.prototype.new = function () { + // parse arguments + var options = {}; // required! + var callback; + + var args = Array.prototype.slice.call(arguments); + if (utils.isFunction(args[args.length - 1])) { + callback = args.pop(); } - addFunctionsToContract(this, abi); - addEventsToContract(this, abi); + var last = args[args.length - 1]; + if (utils.isObject(last) && !utils.isArray(last)) { + options = args.pop(); + } + + // throw an error if there are no options + + var bytes = encodeConstructorParams(this.abi, args); + options.data += bytes; + + if (!callback) { + var address = web3.eth.sendTransaction(options); + return this.at(address); + } + + var self = this; + web3.eth.sendTransaction(options, function (err, address) { + if (err) { + callback(err); + } + self.at(address, callback); + }); }; -Contract.prototype.call = function () { - console.error('contract.call is deprecated'); - return this; +/** + * Should be called to get access to existing contract on a blockchain + * + * @method at + * @param {Address} contract address (required) + * @param {Function} callback {optional) + * @returns {Contract} returns contract if no callback was passed, + * otherwise calls callback function (err, contract) + */ +ContractFactory.prototype.at = function (address, callback) { + // TODO: address is required + + if (callback) { + callback(null, new Contract(this.abi, address)); + } + return new Contract(this.abi, address); }; -Contract.prototype.sendTransaction = function () { - console.error('contract.sendTransact is deprecated'); - return this; +/** + * Should be called to create new contract instance + * + * @method Contract + * @param {Array} abi + * @param {Address} contract address + */ +var Contract = function (abi, address) { + this.address = address; + addFunctionsToContract(this, abi); + addEventsToContract(this, abi); }; module.exports = contract; diff --git a/lib/web3/eth.js b/lib/web3/eth.js index b955a45ac..87a2b290c 100644 --- a/lib/web3/eth.js +++ b/lib/web3/eth.js @@ -174,6 +174,14 @@ var call = new Method({ inputFormatter: [formatters.inputTransactionFormatter, formatters.inputDefaultBlockNumberFormatter] }); +var estimateGas = new Method({ + name: 'estimateGas', + call: 'eth_estimateGas', + params: 1, + inputFormatter: [formatters.inputTransactionFormatter], + outputFormatter: utils.toDecimal +}); + var compileSolidity = new Method({ name: 'compile.solidity', call: 'eth_compileSolidity', @@ -192,6 +200,18 @@ var compileSerpent = new Method({ params: 1 }); +var submitWork = new Method({ + name: 'submitWork', + call: 'eth_submitWork', + params: 3 +}); + +var getWork = new Method({ + name: 'getWork', + call: 'eth_getWork', + params: 0 +}); + var methods = [ getBalance, getStorageAt, @@ -205,10 +225,13 @@ var methods = [ getTransactionFromBlock, getTransactionCount, call, + estimateGas, sendTransaction, compileSolidity, compileLLL, compileSerpent, + submitWork, + getWork ]; /// @returns an array of objects describing web3.eth api properties diff --git a/lib/web3/function.js b/lib/web3/function.js index 2bbb68423..e9ad5d03a 100644 --- a/lib/web3/function.js +++ b/lib/web3/function.js @@ -14,7 +14,7 @@ You should have received a copy of the GNU Lesser General Public License along with ethereum.js. If not, see . */ -/** +/** * @file function.js * @author Marek Kotewicz * @date 2015 @@ -39,18 +39,23 @@ var SolidityFunction = function (json, address) { this._address = address; }; +SolidityFunction.prototype.extractCallback = function (args) { + if (utils.isFunction(args[args.length - 1])) { + return args.pop(); // modify the args array! + } +}; + /** * Should be used to create payload from arguments * * @method toPayload - * @param {...} solidity function params + * @param {Array} solidity function params * @param {Object} optional payload options */ -SolidityFunction.prototype.toPayload = function () { - var args = Array.prototype.slice.call(arguments); +SolidityFunction.prototype.toPayload = function (args) { var options = {}; if (args.length > this._inputTypes.length && utils.isObject(args[args.length -1])) { - options = args.pop(); + options = args[args.length - 1]; } options.to = this._address; options.data = '0x' + this.signature() + coder.encodeParams(this._inputTypes, args); @@ -67,19 +72,41 @@ SolidityFunction.prototype.signature = function () { return web3.sha3(web3.fromAscii(this._name)).slice(2, 10); }; + +SolidityFunction.prototype.unpackOutput = function (output) { + if (output === null) { + return; + } + + output = output.length >= 2 ? output.slice(2) : output; + var result = coder.decodeParams(this._outputTypes, output); + return result.length === 1 ? result[0] : result; +}; + /** - * Should be used to call function - * + * Calls a contract function. + * * @method call - * @param {Object} options + * @param {...Object} Contract function arguments + * @param {function} If the last argument is a function, the contract function + * call will be asynchronous, and the callback will be passed the + * error and result. * @return {String} output bytes */ SolidityFunction.prototype.call = function () { - var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); - var output = web3.eth.call(payload); - output = output.length >= 2 ? output.slice(2) : output; - var result = coder.decodeParams(this._outputTypes, output); - return result.length === 1 ? result[0] : result; + var args = Array.prototype.slice.call(arguments); + var callback = this.extractCallback(args); + var payload = this.toPayload(args); + + if (!callback) { + var output = web3.eth.call(payload); + return this.unpackOutput(output); + } + + var self = this; + web3.eth.call(payload, function (error, output) { + callback(error, self.unpackOutput(output)); + }); }; /** @@ -89,8 +116,16 @@ SolidityFunction.prototype.call = function () { * @param {Object} options */ SolidityFunction.prototype.sendTransaction = function () { - var payload = this.toPayload.apply(this, Array.prototype.slice.call(arguments)); - web3.eth.sendTransaction(payload); + var args = Array.prototype.slice.call(arguments); + var callback = this.extractCallback(args); + var payload = this.toPayload(args); + + if (!callback) { + web3.eth.sendTransaction(payload); + return; + } + + web3.eth.sendTransaction(payload, callback); }; /** @@ -105,7 +140,7 @@ SolidityFunction.prototype.displayName = function () { /** * Should be used to get function type name - * + * * @method typeName * @return {String} type name of the function */ @@ -113,6 +148,25 @@ SolidityFunction.prototype.typeName = function () { return utils.extractTypeName(this._name); }; +/** + * Should be called to get rpc requests from solidity function + * + * @method request + * @returns {Object} + */ +SolidityFunction.prototype.request = function () { + var args = Array.prototype.slice.call(arguments); + var callback = this.extractCallback(args); + var payload = this.toPayload(args); + var format = this.unpackOutput.bind(this); + + return { + callback: callback, + payload: payload, + format: format + }; +}; + /** * Should be called to execute function * @@ -120,7 +174,7 @@ SolidityFunction.prototype.typeName = function () { */ SolidityFunction.prototype.execute = function () { var transaction = !this._constant; - + // send transaction if (transaction) { return this.sendTransaction.apply(this, Array.prototype.slice.call(arguments)); @@ -138,6 +192,7 @@ SolidityFunction.prototype.execute = function () { */ SolidityFunction.prototype.attachToContract = function (contract) { var execute = this.execute.bind(this); + execute.request = this.request.bind(this); execute.call = this.call.bind(this); execute.sendTransaction = this.sendTransaction.bind(this); var displayName = this.displayName(); diff --git a/lib/web3/method.js b/lib/web3/method.js index 449388dd3..8f10b2dfe 100644 --- a/lib/web3/method.js +++ b/lib/web3/method.js @@ -54,7 +54,6 @@ Method.prototype.extractCallback = function (args) { if (utils.isFunction(args[args.length - 1])) { return args.pop(); // modify the args array! } - return null; }; /** @@ -107,6 +106,7 @@ Method.prototype.formatOutput = function (result) { */ Method.prototype.attachToObject = function (obj) { var func = this.send.bind(this); + func.request = this.request.bind(this); func.call = this.call; // that's ugly. filter.js uses it var name = this.name.split('.'); if (name.length > 1) { @@ -137,6 +137,19 @@ Method.prototype.toPayload = function (args) { }; }; +/** + * Should be called to create pure JSONRPC request which can be used in batch request + * + * @method request + * @param {...} params + * @return {Object} jsonrpc request + */ +Method.prototype.request = function () { + var payload = this.toPayload(Array.prototype.slice.call(arguments)); + payload.format = this.formatOutput.bind(this); + return payload; +}; + /** * Should send request to the API * @@ -149,7 +162,7 @@ Method.prototype.send = function () { if (payload.callback) { var self = this; return RequestManager.getInstance().sendAsync(payload, function (err, result) { - payload.callback(null, self.formatOutput(result)); + payload.callback(err, self.formatOutput(result)); }); } return this.formatOutput(RequestManager.getInstance().send(payload)); diff --git a/lib/web3/property.js b/lib/web3/property.js index bfcbb2d25..a2e7282e9 100644 --- a/lib/web3/property.js +++ b/lib/web3/property.js @@ -63,16 +63,23 @@ Property.prototype.formatOutput = function (result) { Property.prototype.attachToObject = function (obj) { var proto = { get: this.get.bind(this), - set: this.set.bind(this) }; - var name = this.name.split('.'); - if (name.length > 1) { - obj[name[0]] = obj[name[0]] || {}; - Object.defineProperty(obj[name[0]], name[1], proto); - } else { - Object.defineProperty(obj, name[0], proto); + var names = this.name.split('.'); + var name = names[0]; + if (names.length > 1) { + obj[names[0]] = obj[names[0]] || {}; + obj = obj[names[0]]; + name = names[1]; } + + Object.defineProperty(obj, name, proto); + + var toAsyncName = function (prefix, name) { + return prefix + name.charAt(0).toUpperCase() + name.slice(1); + }; + + obj[toAsyncName('get', name)] = this.getAsync.bind(this); }; /** @@ -88,15 +95,20 @@ Property.prototype.get = function () { }; /** - * Should be used to set value of the property + * Should be used to asynchrounously get value of property * - * @method set - * @param {Object} new value of the property + * @method getAsync + * @param {Function} */ -Property.prototype.set = function (value) { - return RequestManager.getInstance().send({ - method: this.setter, - params: [this.formatInput(value)] +Property.prototype.getAsync = function (callback) { + var self = this; + RequestManager.getInstance().sendAsync({ + method: this.getter + }, function (err, result) { + if (err) { + return callback(err); + } + callback(err, self.formatOutput(result)); }); }; diff --git a/lib/web3/requestmanager.js b/lib/web3/requestmanager.js index 87eeb8a29..73a18881a 100644 --- a/lib/web3/requestmanager.js +++ b/lib/web3/requestmanager.js @@ -105,6 +105,33 @@ RequestManager.prototype.sendAsync = function (data, callback) { }); }; +/** + * Should be called to asynchronously send batch request + * + * @method sendBatch + * @param {Array} batch data + * @param {Function} callback + */ +RequestManager.prototype.sendBatch = function (data, callback) { + if (!this.provider) { + return callback(errors.InvalidProvider()); + } + + var payload = Jsonrpc.getInstance().toBatchPayload(data); + + this.provider.sendAsync(payload, function (err, results) { + if (err) { + return callback(err); + } + + if (!utils.isArray(results)) { + return callback(errors.InvalidResponse(results)); + } + + callback(err, results); + }); +}; + /** * Should be used to set provider of request manager * diff --git a/lib/web3/watches.js b/lib/web3/watches.js index 0b2c1bd3b..8bcfe207b 100644 --- a/lib/web3/watches.js +++ b/lib/web3/watches.js @@ -25,7 +25,20 @@ var Method = require('./method'); /// @returns an array of objects describing web3.eth.filter api methods var eth = function () { var newFilterCall = function (args) { - return typeof args[0] === 'string' ? 'eth_newBlockFilter' : 'eth_newFilter'; + var type = args[0]; + + switch(type) { + case 'latest': + args.pop(); + this.params = 0; + return 'eth_newBlockFilter'; + case 'pending': + args.pop(); + this.params = 0; + return 'eth_newPendingTransactionFilter'; + default: + return 'eth_newFilter'; + } }; var newFilter = new Method({ diff --git a/package.js b/package.js index bfb8d0556..953edb4fb 100644 --- a/package.js +++ b/package.js @@ -1,7 +1,7 @@ /* jshint ignore:start */ Package.describe({ name: 'ethereum:web3', - version: '0.3.6', + version: '0.4.2', 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/package.json b/package.json index 4c7c81445..59d4f6211 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "web3", "namespace": "ethereum", - "version": "0.3.6", + "version": "0.4.2", "description": "Ethereum JavaScript API, middleware to talk to a ethereum node over RPC", "main": "./index.js", "directories": { diff --git a/test/abi.formatConstructorParams.js b/test/abi.formatConstructorParams.js deleted file mode 100644 index 9113f02c6..000000000 --- a/test/abi.formatConstructorParams.js +++ /dev/null @@ -1,106 +0,0 @@ -var chai = require('chai'); -var assert = require('assert'); -var abi = require('../lib/solidity/abi'); - -describe('lib/solidity/abi', function () { - describe('formatConstructorParams', function () { - it('should format uint256 properly', function () { - // given - var description = [{ - "name": "test", - "type": "constructor", - "inputs": [{ - "name": "a", - "type": "uint256" - } - ] - }]; - - // when - var bytes = abi.formatConstructorParams(description, [2]); - - // then - assert.equal(bytes, '0000000000000000000000000000000000000000000000000000000000000002'); - }); - - it('should not find matching constructor', function () { - // given - var description = [{ - "name": "test", - "type": "constructor", - "inputs": [{ - "name": "a", - "type": "uint256" - } - ] - }]; - - // when - var bytes = abi.formatConstructorParams(description, []); - - // then - assert.equal(bytes, ''); - }); - - it('should not find matching constructor2', function () { - // given - var description = [{ - "name": "test", - "type": "constructor", - "inputs": [{ - "name": "a", - "type": "uint256" - } - ] - }]; - - // when - var bytes = abi.formatConstructorParams(description, [1,2]); - - // then - assert.equal(bytes, ''); - }); - - it('should not find matching constructor3', function () { - // given - var description = [{ - "name": "test", - "type": "function", - "inputs": [{ - "name": "a", - "type": "uint256" - } - ] - }]; - - // when - var bytes = abi.formatConstructorParams(description, [2]); - - // then - assert.equal(bytes, ''); - }); - - it('should find matching constructor with multiple args', function () { - // given - var description = [{ - "name": "test", - "type": "constructor", - "inputs": [{ - "name": "a", - "type": "uint256" - }, { - "name": "b", - "type": "uint256" - }] - }]; - - // when - var bytes = abi.formatConstructorParams(description, ['1', '5']); - - // then - assert.equal(bytes, '00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000005'); - }); - }); -}); - - diff --git a/test/async.js b/test/async.js new file mode 100644 index 000000000..77497603c --- /dev/null +++ b/test/async.js @@ -0,0 +1,69 @@ +var chai = require('chai'); +var assert = chai.assert; +var web3 = require('../index'); +var FakeHttpProvider = require('./helpers/FakeHttpProvider'); + +// use sendTransaction as dummy +var method = 'sendTransaction'; + +var tests = [{ + result: '0xb', + formattedResult: '0xb', + call: 'eth_'+ method +}]; + +describe('async', function () { + tests.forEach(function (test, index) { + it('test: ' + index, function (done) { + + // 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 + web3.eth[method]({}, function(error, result){ + + // then + assert.isNull(error); + assert.strictEqual(test.formattedResult, result); + + done(); + }); + + }); + + it('error test: ' + index, function (done) { + + // given + var provider = new FakeHttpProvider(); + web3.setProvider(provider); + provider.injectError({ + message: test.result, + code: -32603 + }); + provider.injectValidation(function (payload) { + assert.equal(payload.jsonrpc, '2.0'); + assert.equal(payload.method, test.call); + assert.deepEqual(payload.params, [{}]); + }); + + // when + web3.eth[method]({}, function(error, result){ + + // then + assert.isUndefined(result); + assert.strictEqual(test.formattedResult, error.message); + + done(); + }); + + }); + }); +}); + diff --git a/test/batch.js b/test/batch.js new file mode 100644 index 000000000..69ae8fd58 --- /dev/null +++ b/test/batch.js @@ -0,0 +1,86 @@ +var chai = require('chai'); +var assert = chai.assert; +var web3 = require('../index'); +var FakeHttpProvider = require('./helpers/FakeHttpProvider'); +var bn = require('bignumber.js'); + +describe('lib/web3/batch', function () { + describe('execute', function () { + it('should execute batch request', function (done) { + + var provider = new FakeHttpProvider(); + web3.setProvider(provider); + web3.reset(); + + var result = '0x126'; + var result2 = '0x127'; + provider.injectBatchResults([result, result2]); + + var counter = 0; + var callback = function (err, r) { + counter++; + assert.deepEqual(new bn(result), r); + }; + + var callback2 = function (err, r) { + assert.equal(counter, 1); + assert.deepEqual(new bn(result2), r); + done(); + }; + + var batch = web3.createBatch(); + batch.add(web3.eth.getBalance.request('0x0000000000000000000000000000000000000000', 'latest', callback)); + batch.add(web3.eth.getBalance.request('0x0000000000000000000000000000000000000005', 'latest', callback2)); + batch.execute(); + }); + + it('should execute batch request', function (done) { + + var provider = new FakeHttpProvider(); + web3.setProvider(provider); + web3.reset(); + + var abi = [{ + "name": "balance(address)", + "type": "function", + "inputs": [{ + "name": "who", + "type": "address" + }], + "constant": true, + "outputs": [{ + "name": "value", + "type": "uint256" + }] + }]; + + + var address = '0x0000000000000000000000000000000000000000'; + var result = '0x126'; + var result2 = '0x0000000000000000000000000000000000000000000000000000000000000123'; + var signature = '0x001122334455'; + + // TODO: fix this, maybe in browser sha3? + provider.injectResult(signature); + + var counter = 0; + var callback = function (err, r) { + counter++; + assert.deepEqual(new bn(result), r); + }; + + var callback2 = function (err, r) { + assert.equal(counter, 1); + assert.deepEqual(new bn(result2), r); + done(); + }; + + var batch = web3.createBatch(); + batch.add(web3.eth.getBalance.request('0x0000000000000000000000000000000000000000', 'latest', callback)); + batch.add(web3.eth.contract(abi).at(address).balance.request(address, callback2)); + provider.injectBatchResults([result, result2]); + batch.execute(); + }); + }); +}); + diff --git a/test/contract.js b/test/contract.js index 0dcaa1003..a46a8cab3 100644 --- a/test/contract.js +++ b/test/contract.js @@ -116,8 +116,7 @@ describe('web3.eth.contract', function () { } }); - var Contract = web3.eth.contract(desc); - var contract = new Contract(address); + var contract = web3.eth.contract(desc).at(address); var res = 0; contract.Changed({from: address}).watch(function(err, result) { @@ -155,8 +154,7 @@ describe('web3.eth.contract', function () { } }); - var Contract = web3.eth.contract(desc); - var contract = new Contract(address); + var contract = web3.eth.contract(desc).at(address); contract.balance(address); }); @@ -186,8 +184,7 @@ describe('web3.eth.contract', function () { } }); - var Contract = web3.eth.contract(desc); - var contract = new Contract(address); + var contract = web3.eth.contract(desc).at(address); contract.send(address, 17); }); @@ -218,8 +215,7 @@ describe('web3.eth.contract', function () { } }); - var Contract = web3.eth.contract(desc); - var contract = new Contract(address); + var contract = web3.eth.contract(desc).at(address); contract.balance(address, {from: address, gas: 50000}); @@ -251,8 +247,7 @@ describe('web3.eth.contract', function () { } }); - var Contract = web3.eth.contract(desc); - var contract = new Contract(address); + var contract = web3.eth.contract(desc).at(address); contract.balance.call(address, {from: address, gas: 50000}); @@ -287,8 +282,7 @@ describe('web3.eth.contract', function () { } }); - var Contract = web3.eth.contract(desc); - var contract = new Contract(address); + var contract = web3.eth.contract(desc).at(address); contract.send(address, 17, {from: address, gas: 50000, gasPrice: 3000, value: 10000}); }); @@ -322,12 +316,48 @@ describe('web3.eth.contract', function () { } }); - var Contract = web3.eth.contract(desc); - var contract = new Contract(address); + var contract = web3.eth.contract(desc).at(address); contract.send.sendTransaction(address, 17, {from: address, gas: 50000, gasPrice: 3000, value: 10000}); }); + it('should explicitly sendTransaction with optional params and call callback without error', function (done) { + var provider = new FakeHttpProvider(); + web3.setProvider(provider); + web3.reset(); + var sha3 = '0x5131231231231231231231'; + var address = '0x1234567890123456789012345678901234567890'; + provider.injectResult(sha3); + var step = 0; + provider.injectValidation(function (payload) { + if (step === 0) { + step = 1; + assert.equal(payload.jsonrpc, '2.0'); + assert.equal(payload.method, 'web3_sha3'); + assert.equal(payload.params[0], web3.fromAscii('send(address,uint256)')); + } else if (step === 1) { + assert.equal(payload.method, 'eth_sendTransaction'); + assert.deepEqual(payload.params, [{ + data: sha3.slice(0, 10) + + '0000000000000000000000001234567890123456789012345678901234567890' + + '0000000000000000000000000000000000000000000000000000000000000011' , + to: address, + from: address, + gas: '0xc350', + gasPrice: '0xbb8', + value: '0x2710' + }]); + } + }); + + var contract = web3.eth.contract(desc).at(address); + + contract.send.sendTransaction(address, 17, {from: address, gas: 50000, gasPrice: 3000, value: 10000}, function (err) { + assert.equal(err, null); + done(); + }); + }); + it('should call testArr method and properly parse result', function () { var provider = new FakeHttpProvider2(); web3.setProvider(provider); @@ -356,12 +386,48 @@ describe('web3.eth.contract', function () { step++; }); - var Contract = web3.eth.contract(desc); - var contract = new Contract(address); - + var contract = web3.eth.contract(desc).at(address); var result = contract.testArr([3]); assert.deepEqual(new BigNumber(5), result); }); + + it('should call testArr method, properly parse result and return the result async', function (done) { + var provider = new FakeHttpProvider2(); + web3.setProvider(provider); + web3.reset(); + var sha3 = '0x5131231231231231231231'; + var address = '0x1234567890123456789012345678901234567890'; + provider.injectResultList([{ + result: sha3 + }, { + result: '0x0000000000000000000000000000000000000000000000000000000000000005' + }]); + var step = 0; + provider.injectValidation(function (payload) { + if (step === 1) { // getting sha3 is first + assert.equal(payload.method, 'eth_call'); + assert.deepEqual(payload.params, [{ + data: sha3.slice(0, 10) + + '0000000000000000000000000000000000000000000000000000000000000020' + + '0000000000000000000000000000000000000000000000000000000000000001' + + '0000000000000000000000000000000000000000000000000000000000000003', + to: address + }, + 'latest' + ]); + } + step++; + }); + + var contract = web3.eth.contract(desc).at(address); + + contract.testArr([3], function (err, result) { + assert.deepEqual(new BigNumber(5), result); + done(); + }); + + }); }); }); + diff --git a/test/method.request.js b/test/method.request.js new file mode 100644 index 000000000..00bf52cb7 --- /dev/null +++ b/test/method.request.js @@ -0,0 +1,23 @@ +var chai = require('chai'); +var assert = chai.assert; +var web3 = require('../index'); + +describe('lib/web3/method', function () { + describe('request', function () { + it('should create proper request', function () { + + var callback = function (err, result) {}; + var expected = { + method: 'eth_getBalance', + callback: callback, + params: ['0x0000000000000000000000000000000000000000', 'latest'], + }; + + var request = web3.eth.getBalance.request('0x0000000000000000000000000000000000000000', 'latest', callback); + + expected.format = request.format; + assert.deepEqual(request, expected); + }); + }); +}); + diff --git a/test/node/app.js b/test/node/app.js index c3fd489a0..9ec310f44 100644 --- a/test/node/app.js +++ b/test/node/app.js @@ -1,4 +1,4 @@ -var web3 = require('ethereum.js'); +var web3 = require('web3'); console.log(web3.version.api); diff --git a/test/node/package.json b/test/node/package.json index 4c56b2c10..310ad2e04 100644 --- a/test/node/package.json +++ b/test/node/package.json @@ -9,6 +9,6 @@ "author": "", "license": "ISC", "dependencies": { - "ethereum.js": "ethereum/ethereum.js#master" + "web3": "ethereum/web3.js#master" } } diff --git a/test/polling.js b/test/polling.js index ea7dd9829..8bd2b041c 100644 --- a/test/polling.js +++ b/test/polling.js @@ -6,15 +6,26 @@ var utils = require('../lib/utils/utils'); var tests = [{ protocol: 'eth', - args: ['pending'], + args: ['latest'], firstResult: 1, firstPayload: { method: "eth_newBlockFilter", - params: [ - "pending" - ] + params: [] + }, + secondResult: ['0x1234'], + secondPayload: { + method: "eth_getFilterChanges" + } +}, +{ + protocol: 'eth', + args: ['pending'], + firstResult: 1, + firstPayload: { + method: "eth_newPendingTransactionFilter", + params: [] }, - secondResult: [null], + secondResult: ['0x1234'], secondPayload: { method: "eth_getFilterChanges" } diff --git a/test/web3.eth.blockNumber.js b/test/web3.eth.blockNumber.js index dfd73f57e..dbe7f1c44 100644 --- a/test/web3.eth.blockNumber.js +++ b/test/web3.eth.blockNumber.js @@ -32,6 +32,26 @@ describe('web3.eth', function () { // then assert.strictEqual(test.formattedResult, result); }); + + it('async get property test: ' + index, function (done) { + + // 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 + web3.eth.getBlockNumber(function (err, result) { + assert.strictEqual(test.formattedResult, result); + done(); + }); + + }); }); }); }); diff --git a/test/web3.eth.call.js b/test/web3.eth.call.js new file mode 100644 index 000000000..d79bd64d4 --- /dev/null +++ b/test/web3.eth.call.js @@ -0,0 +1,41 @@ +var web3 = require('../index'); +var testMethod = require('./helpers/test.method.js'); + +var method = 'call'; + +var tests = [{ + args: [{ + to: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b', + data: '0x23455654', + gas: 11, + gasPrice: 11 + }], + formattedArgs: [{ + to: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b', + data: '0x23455654', + gas: '0xb', + gasPrice: '0xb' + }, 'latest'], + result: '0x31981', + formattedResult: '0x31981', + call: 'eth_'+ method +},{ + args: [{ + to: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b', + data: '0x23455654', + gas: 11, + gasPrice: 11 + }, 11], + formattedArgs: [{ + to: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b', + data: '0x23455654', + gas: '0xb', + gasPrice: '0xb' + }, '0xb'], + result: '0x31981', + formattedResult: '0x31981', + call: 'eth_'+ method +}]; + +testMethod.runTests('eth', method, tests); + diff --git a/test/web3.eth.contract.js b/test/web3.eth.contract.js index 651810b69..b089f0243 100644 --- a/test/web3.eth.contract.js +++ b/test/web3.eth.contract.js @@ -25,8 +25,7 @@ describe('web3.eth.contract', function() { var address = '0x1234567890123456789012345678901234567890'; // when - var Con = contract(description); - var myCon = new Con(address); + var myCon = contract(description).at(address); // then assert.equal('function', typeof myCon.test); @@ -54,8 +53,7 @@ describe('web3.eth.contract', function() { var address = '0x1234567890123456789012345678901234567890'; // when - var Con = contract(description); - var myCon = new Con(address); + var myCon = contract(description).at(address); // then assert.equal('function', typeof myCon.test); @@ -97,8 +95,7 @@ describe('web3.eth.contract', function() { var address = '0x1234567890123456789012345678901234567890'; // when - var Con = contract(description); - var myCon = new Con(address); + var myCon = contract(description).at(address); // then assert.equal('function', typeof myCon.test); @@ -142,8 +139,7 @@ describe('web3.eth.contract', function() { var address = '0x1234567890123456789012345678901234567890'; // when - var Con = contract(description); - var myCon = new Con(address); + var myCon = contract(description).at(address); // then assert.equal('function', typeof myCon.test); @@ -171,8 +167,7 @@ describe('web3.eth.contract', function() { var address = '0x1234567890123456789012345678901234567890'; // when - var Con = contract(description); - var myCon = new Con(address); + var myCon = contract(description).at(address); // then assert.equal('undefined', typeof myCon.test); @@ -200,8 +195,7 @@ describe('web3.eth.contract', function() { var address = '0x1234567890123456789012345678901234567890'; // when - var Con = contract(description); - var myCon = new Con(address); + var myCon = contract(description).at(address); // then assert.equal('function', typeof myCon.test); @@ -233,8 +227,7 @@ describe('web3.eth.contract', function() { done(); }); - var Con = contract(description); - var myCon = new Con({data: code}, 2); + var myCon = contract(description).new(2, {data: code}); }); }); diff --git a/test/web3.eth.estimateGas.js b/test/web3.eth.estimateGas.js new file mode 100644 index 000000000..efa6bf310 --- /dev/null +++ b/test/web3.eth.estimateGas.js @@ -0,0 +1,25 @@ +var web3 = require('../index'); +var testMethod = require('./helpers/test.method.js'); + +var method = 'estimateGas'; + +var tests = [{ + args: [{ + to: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b', + data: '0x23455654', + gas: 11, + gasPrice: 11 + }], + formattedArgs: [{ + to: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b', + data: '0x23455654', + gas: '0xb', + gasPrice: '0xb' + }], + result: '0x31981', + formattedResult: 203137, + call: 'eth_'+ method +}]; + +testMethod.runTests('eth', method, tests); + diff --git a/test/web3.eth.filter.js b/test/web3.eth.filter.js index 7a355b50c..9f196b349 100644 --- a/test/web3.eth.filter.js +++ b/test/web3.eth.filter.js @@ -37,11 +37,17 @@ var tests = [{ formattedResult: '0xf', call: 'eth_newFilter' },{ - args: ['pending'], - formattedArgs: ['pending'], + args: ['latest'], + formattedArgs: [], result: '0xf', formattedResult: '0xf', call: 'eth_newBlockFilter' +},{ + args: ['pending'], + formattedArgs: [], + result: '0xf', + formattedResult: '0xf', + call: 'eth_newPendingTransactionFilter' }]; describe('web3.eth', function () { diff --git a/test/web3.eth.getWork.js b/test/web3.eth.getWork.js new file mode 100644 index 000000000..181c1894b --- /dev/null +++ b/test/web3.eth.getWork.js @@ -0,0 +1,16 @@ +var chai = require('chai'); +var web3 = require('../index'); +var testMethod = require('./helpers/test.method.js'); + +var method = 'getWork'; + +var tests = [{ + args: [], + formattedArgs: [], + result: true, + formattedResult: true, + call: 'eth_'+ method +}]; + +testMethod.runTests('eth', method, tests); + diff --git a/test/web3.eth.submitWork.js b/test/web3.eth.submitWork.js new file mode 100644 index 000000000..3751c8073 --- /dev/null +++ b/test/web3.eth.submitWork.js @@ -0,0 +1,17 @@ +var chai = require('chai'); +var web3 = require('../index'); +var testMethod = require('./helpers/test.method.js'); + +var method = 'submitWork'; + +var tests = [ +{ + args: ['0x567890abcdef5555', '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', '0xcdef1234567890abcdef1234567890abcdef0x1234567890abcf1234567890ab'], + formattedArgs: ['0x567890abcdef5555', '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', '0xcdef1234567890abcdef1234567890abcdef0x1234567890abcf1234567890ab'], + result: true, + formattedResult: true, + call: 'eth_'+ method +}]; + +testMethod.runTests('eth', method, tests); + From 2e2a59596de27988baec83222c7540c2064e22ce Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Thu, 14 May 2015 14:18:35 +0200 Subject: [PATCH 066/157] migration from web3.js 0.3.x -> 0.4.2 --- mix/qml/html/WebContainer.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mix/qml/html/WebContainer.html b/mix/qml/html/WebContainer.html index 9c458a4c7..cd92852a7 100644 --- a/mix/qml/html/WebContainer.html +++ b/mix/qml/html/WebContainer.html @@ -23,8 +23,7 @@ updateContracts = function(contracts) { window.contracts = {}; window.BigNumber = require('bignumber.js'); for (var c in contracts) { - var contractProto = window.web3.eth.contract(contracts[c].interface); - var contract = new contractProto(contracts[c].address); + var contract = window.web3.eth.contract(contracts[c].interface).at(contracts[c].address); window.contracts[c] = { address: contracts[c].address, interface: contracts[c].interface, From 96028db82cc15c2feabed12cc5b0b240af85287a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 14 May 2015 16:19:16 +0300 Subject: [PATCH 067/157] More diagnostics for the BadRoot bug. --- libdevcrypto/OverlayDB.cpp | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/libdevcrypto/OverlayDB.cpp b/libdevcrypto/OverlayDB.cpp index 957c7f0e3..bde6a3644 100644 --- a/libdevcrypto/OverlayDB.cpp +++ b/libdevcrypto/OverlayDB.cpp @@ -38,6 +38,12 @@ OverlayDB::~OverlayDB() cnote << "Closing state DB"; } +class WriteBatchNoter: public ldb::WriteBatch::Handler +{ + virtual void Put(ldb::Slice const& _key, ldb::Slice const& _value) { cnote << "Put" << toHex(bytesConstRef(_key)) << "=>" << toHex(bytesConstRef(_value)); } + virtual void Delete(ldb::Slice const& _key) { cnote << "Delete" << toHex(bytesConstRef(_key)); } +}; + void OverlayDB::commit() { if (m_db) @@ -61,16 +67,27 @@ void OverlayDB::commit() } } - while (true) + for (unsigned i = 0; i < 10; ++i) { ldb::Status o = m_db->Write(m_writeOptions, &batch); if (o.ok()) break; - cwarn << "Error writing to database. Sleeping a while then retrying. If it keeps saying this, free up some space!"; - this_thread::sleep_for(chrono::milliseconds(500)); + if (i == 9) + { + cwarn << "Fail writing to state database. Bombing out."; + exit(-1); + } + cwarn << "Error writing to state database: " << o.ToString(); + WriteBatchNoter n; + batch.Iterate(&n); + cwarn << "Sleeping for" << (i + 1) << "seconds, then retrying."; + this_thread::sleep_for(chrono::seconds(i + 1)); + } + DEV_WRITE_GUARDED(x_this) + { + m_aux.clear(); + m_main.clear(); } - m_aux.clear(); - m_main.clear(); } } From ebe06b37de98d383adc3e955511c9c3e72f8a58e Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 14 May 2015 16:58:56 +0300 Subject: [PATCH 068/157] More stringent checking for ancestors in uncles. Minor fixes to AZ. Optimisations for NewBlockHashes handling. --- alethzero/MainWin.cpp | 3 ++- libethereum/BlockChain.cpp | 5 +++-- libethereum/EthereumHost.cpp | 4 ++-- libethereum/EthereumHost.h | 2 +- libethereum/EthereumPeer.cpp | 2 +- libethereum/State.cpp | 16 +++++++--------- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 7551eaa35..7026cb7c8 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1010,7 +1010,7 @@ void Main::refreshBalances() 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->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); li->setCheckState(m_beneficiary == i.first ? Qt::Checked : Qt::Unchecked); totalBalance += b; @@ -1990,6 +1990,7 @@ void Main::on_killAccount_triggered() m_keyManager.kill(h); if (m_keyManager.accounts().empty()) m_keyManager.import(Secret::random(), "Default account"); + m_beneficiary = *m_keyManager.accounts().begin(); keysChanged(); if (m_beneficiary == h) setBeneficiary(*m_keyManager.accounts().begin()); diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 32a11ee53..7c03bc24f 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -984,11 +984,12 @@ vector BlockChain::withBlockBloom(LogBloom const& _b, unsigned _earlie 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). - h256Hash ret; h256 p = _parent; + h256Hash ret = { p }; + // p and (details(p).parent: i == 5) is likely to be overkill, but can't hurt to be cautious. for (unsigned i = 0; i < 6 && p != m_genesisHash; ++i, p = details(p).parent) { - ret.insert(p); // TODO: check: should this be details(p).parent? + ret.insert(details(p).parent); auto b = block(p); for (auto i: RLP(b)[2]) ret.insert(sha3(i.data())); diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 72ee1854d..1ca77cd1c 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -83,7 +83,7 @@ void EthereumHost::noteNeedsSyncing(EthereumPeer* _who) _who->attemptSync(); } -void EthereumHost::changeSyncer(EthereumPeer* _syncer) +void EthereumHost::changeSyncer(EthereumPeer* _syncer, bool _needHelp) { if (_syncer) clog(NetAllDetail) << "Changing syncer to" << _syncer->session()->socketId(); @@ -93,7 +93,7 @@ void EthereumHost::changeSyncer(EthereumPeer* _syncer) m_syncer = _syncer; if (isSyncing()) { - if (_syncer->m_asking == Asking::Blocks) + if (_needHelp && _syncer->m_asking == Asking::Blocks) for (auto j: peerSessions()) { auto e = j.first->cap().get(); diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index d53c3cc79..95c7f147a 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -108,7 +108,7 @@ private: virtual void onStarting() { startWorking(); } virtual void onStopping() { stopWorking(); } - void changeSyncer(EthereumPeer* _ignore); + void changeSyncer(EthereumPeer* _ignore, bool _needHelp = true); BlockChain const& m_chain; TransactionQueue& m_tq; ///< Maintains a list of incoming transactions not yet in a block on the blockchain. diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp index 85bdf33e9..1d0c9fa0d 100644 --- a/libethereum/EthereumPeer.cpp +++ b/libethereum/EthereumPeer.cpp @@ -600,7 +600,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r) if (unknowns > 0) { host()->m_man.resetToChain(m_syncingNeededBlocks); - host()->changeSyncer(this); + host()->changeSyncer(this, false); transition(Asking::Blocks); } return true; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 167d6236e..ccc6c4512 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -650,25 +650,23 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement if (rlp[2].itemCount() > 2) BOOST_THROW_EXCEPTION(TooManyUncles()); - unordered_set nonces = { m_currentBlock.nonce }; vector rewarded; - h256Hash knownUncles = _bc.allUnclesFrom(m_currentBlock.parentHash); + h256Hash excluded = _bc.allUnclesFrom(m_currentBlock.parentHash); + excluded.insert(m_currentBlock.hash()); for (auto const& i: rlp[2]) { - if (knownUncles.count(sha3(i.data()))) - BOOST_THROW_EXCEPTION(UncleInChain() << errinfo_comment("Uncle in block already mentioned") << errinfo_data(toString(knownUncles)) << errinfo_hash256(sha3(i.data())) ); - - BlockInfo uncle = BlockInfo::fromHeader(i.data()); - if (nonces.count(uncle.nonce)) - BOOST_THROW_EXCEPTION(DuplicateUncleNonce()); + auto h = sha3(i.data()); + if (excluded.count(h)) + BOOST_THROW_EXCEPTION(UncleInChain() << errinfo_comment("Uncle in block already mentioned") << errinfo_data(toString(excluded)) << errinfo_hash256(sha3(i.data()))); + excluded.insert(h); + BlockInfo uncle = BlockInfo::fromHeader(i.data(), CheckEverything, h); BlockInfo uncleParent(_bc.block(uncle.parentHash)); if ((bigint)uncleParent.number < (bigint)m_currentBlock.number - 7) BOOST_THROW_EXCEPTION(UncleTooOld()); uncle.verifyParent(uncleParent); - nonces.insert(uncle.nonce); // tdIncrease += uncle.difficulty; rewarded.push_back(uncle); } From 5b678eca8a17a1d8057a27895eb69087837eadce Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 14 May 2015 16:17:32 +0200 Subject: [PATCH 069/157] add in chain uncle test for every generation --- .../BlockTestsFiller/bcUncleTestFiller.json | 668 ++++++++++++++++++ 1 file changed, 668 insertions(+) diff --git a/test/libethereum/BlockTestsFiller/bcUncleTestFiller.json b/test/libethereum/BlockTestsFiller/bcUncleTestFiller.json index e67cfeecd..f700dc7ad 100644 --- a/test/libethereum/BlockTestsFiller/bcUncleTestFiller.json +++ b/test/libethereum/BlockTestsFiller/bcUncleTestFiller.json @@ -492,6 +492,674 @@ ] }, + + "InChainUncleFather" : { + "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" : "20" + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "nonce" : "2" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + { + "sameAsBlock" : "2" + } + ] + } + ] + }, + + "InChainUncleGrandPa" : { + "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" : "20" + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "nonce" : "2" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + { + "sameAsBlock" : "1" + } + ] + } + ] + }, + + + "InChainUncleGreatGrandPa" : { + "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" : "20" + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "nonce" : "2" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + { + "sameAsBlock" : "1" + } + ] + } + ] + }, + + "InChainUncleGreatGreatGrandPa" : { + "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" : "20" + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "nonce" : "2" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "4", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + { + "sameAsBlock" : "1" + } + ] + } + ] + }, + + "InChainUncleGreatGreatGreatGrandPa" : { + "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" : "20" + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "nonce" : "2" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "4", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "5", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + { + "sameAsBlock" : "1" + } + ] + } + ] + }, + + "InChainUncleGreatGreatGreatGreatGrandPa" : { + "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" : "20" + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "nonce" : "2" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "4", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "5", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "314159", + "gasPrice" : "1", + "nonce" : "6", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + { + "sameAsBlock" : "1" + } + ] + } + ] + }, + "twoEqualUncle" : { "genesisBlockHeader" : { "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", From 3802e4110e2a707c98f81868acab6024568964f7 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 14 May 2015 16:20:42 +0200 Subject: [PATCH 070/157] correct expext value for in chain uncle tests --- .../BlockTestsFiller/bcUncleTestFiller.json | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/test/libethereum/BlockTestsFiller/bcUncleTestFiller.json b/test/libethereum/BlockTestsFiller/bcUncleTestFiller.json index f700dc7ad..aeb372f67 100644 --- a/test/libethereum/BlockTestsFiller/bcUncleTestFiller.json +++ b/test/libethereum/BlockTestsFiller/bcUncleTestFiller.json @@ -103,7 +103,7 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "30" }, @@ -204,7 +204,7 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "30" }, @@ -305,7 +305,7 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20" }, @@ -406,7 +406,7 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20" }, @@ -511,7 +511,7 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20" }, @@ -597,7 +597,7 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20" }, @@ -684,12 +684,12 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20" + "balance" : "30" }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "nonce" : "2" + "nonce" : "3" } }, "pre" : { @@ -785,12 +785,12 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20" + "balance" : "40" }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "nonce" : "2" + "nonce" : "4" } }, "pre" : { @@ -901,12 +901,12 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20" + "balance" : "50" }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "nonce" : "2" + "nonce" : "5" } }, "pre" : { @@ -1032,12 +1032,12 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "20" + "balance" : "60" }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "nonce" : "2" + "nonce" : "6" } }, "pre" : { @@ -1178,7 +1178,7 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20" }, @@ -1282,7 +1282,7 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "30" }, @@ -1407,7 +1407,7 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "20" }, @@ -1544,7 +1544,7 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "40" }, @@ -1663,7 +1663,7 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "50" }, @@ -1797,7 +1797,7 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "60" }, @@ -1946,7 +1946,7 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "70" }, @@ -2110,7 +2110,7 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "80" }, @@ -2289,7 +2289,7 @@ "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, - "expect" : { + "expect" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "80" }, From 4409bc5d7d437f5354218dc3e2061027eadffccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 14 May 2015 16:39:40 +0200 Subject: [PATCH 071/157] Tests: SMOD edge case test. --- .../VMTestsFiller/vmArithmeticTestFiller.json | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json b/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json index 76771982e..72c90e912 100644 --- a/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json +++ b/test/libevm/VMTestsFiller/vmArithmeticTestFiller.json @@ -2031,6 +2031,76 @@ } }, + "smod_i256min1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "storage" : { + "0x" : "0x8000000000000000000000000000000000000000000000000000000000000000" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (SMOD (- 0 57896044618658097711785492504343953926634992332820282019728792003956564819968) (- 0 1) ) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + + "smod_i256min2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "expect" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "storage" : { + "0x" : "0x8000000000000000000000000000000000000000000000000000000000000000" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{ [[ 0 ]] (- (SMOD (- 0 57896044618658097711785492504343953926634992332820282019728792003956564819968) (- 0 1) ) 1) }", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + "addmod0": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", From 9cd64dcfe570975acfe5e49d7dec71b95a225b98 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 14 May 2015 17:14:21 +0200 Subject: [PATCH 072/157] Probably fix for BadRoot bug. --- libethereum/State.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index ccc6c4512..f5739aadb 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -62,6 +62,7 @@ OverlayDB State::openDB(std::string _path, WithExisting _we) boost::filesystem::remove_all(_path + "/state"); ldb::Options o; + o.max_open_files = 256; o.create_if_missing = true; ldb::DB* db = nullptr; ldb::DB::Open(o, _path + "/state", &db); From 802024ba0e5ad2693c901301f3db2cf9a708addc Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 14 May 2015 17:14:40 +0200 Subject: [PATCH 073/157] Bump. --- libdevcore/Common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 28b537be5..1ffa66f14 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -28,7 +28,7 @@ using namespace dev; namespace dev { -char const* Version = "0.9.20"; +char const* Version = "0.9.21"; const u256 UndefinedU256 = ~(u256)0; From eb8dc43e8a9c83313bbd9a8e898437ce12a5cef6 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 14 May 2015 17:52:53 +0200 Subject: [PATCH 074/157] Make terms more clear for uncle exclusion API. --- libethereum/BlockChain.cpp | 4 ++-- libethereum/BlockChain.h | 6 +++--- libethereum/State.cpp | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 7c03bc24f..68eccddf5 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -981,13 +981,13 @@ vector BlockChain::withBlockBloom(LogBloom const& _b, unsigned _earlie return ret; } -h256Hash BlockChain::allUnclesFrom(h256 const& _parent) const +h256Hash BlockChain::allKinFrom(h256 const& _parent, unsigned _generations) const { // Get all uncles cited given a parent (i.e. featured as uncles/main in parent, parent + 1, ... parent + 5). h256 p = _parent; h256Hash ret = { p }; // p and (details(p).parent: i == 5) is likely to be overkill, but can't hurt to be cautious. - for (unsigned i = 0; i < 6 && p != m_genesisHash; ++i, p = details(p).parent) + for (unsigned i = 0; i < _generations && p != m_genesisHash; ++i, p = details(p).parent) { ret.insert(details(p).parent); auto b = block(p); diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index e77369534..02f3f618a 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -203,10 +203,10 @@ public: /// Get the hash of the genesis block. Thread-safe. h256 genesisHash() const { return m_genesisHash; } - /// 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 + /// Get all blocks not allowed as uncles given a parent (i.e. featured as uncles/main in parent, parent + 1, ... parent + @a _generations). + /// @returns set including the header-hash of every parent (including @a _parent) up to and including generation + @a _generations /// togther with all their quoted uncles. - h256Hash allUnclesFrom(h256 const& _parent) const; + h256Hash allKinFrom(h256 const& _parent, unsigned _generations) 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/State.cpp b/libethereum/State.cpp index f5739aadb..67fa5395b 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -652,7 +652,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement BOOST_THROW_EXCEPTION(TooManyUncles()); vector rewarded; - h256Hash excluded = _bc.allUnclesFrom(m_currentBlock.parentHash); + h256Hash excluded = _bc.allKinFrom(m_currentBlock.parentHash, 6); excluded.insert(m_currentBlock.hash()); for (auto const& i: rlp[2]) @@ -816,7 +816,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; - h256Hash knownUncles = _bc.allUnclesFrom(m_currentBlock.parentHash); + h256Hash knownUncles = _bc.allKinFrom(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) { From b50d44b8ac8229bbebe58e7d21b84c720e961d6a Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 14 May 2015 19:48:01 +0200 Subject: [PATCH 075/157] Trie optimizations --- libdevcrypto/OverlayDB.cpp | 2 +- libdevcrypto/TrieDB.h | 93 ++++++++++++++++++++++++-------------- libethcore/Common.cpp | 3 +- test/libdevcrypto/trie.cpp | 61 +++++++++++++++++++++++-- 4 files changed, 119 insertions(+), 40 deletions(-) diff --git a/libdevcrypto/OverlayDB.cpp b/libdevcrypto/OverlayDB.cpp index bde6a3644..80c901635 100644 --- a/libdevcrypto/OverlayDB.cpp +++ b/libdevcrypto/OverlayDB.cpp @@ -94,7 +94,7 @@ void OverlayDB::commit() bytes OverlayDB::lookupAux(h256 const& _h) const { bytes ret = MemoryDB::lookupAux(_h); - if (!ret.empty()) + if (!ret.empty() || !m_db) return move(ret); std::string v; bytes b = _h.asBytes(); diff --git a/libdevcrypto/TrieDB.h b/libdevcrypto/TrieDB.h index 29b412bab..cf85148d2 100644 --- a/libdevcrypto/TrieDB.h +++ b/libdevcrypto/TrieDB.h @@ -220,6 +220,7 @@ public: bool operator!=(Node const& _c) const { return !operator==(_c); } }; + protected: std::vector m_trail; GenericTrieDB const* m_that; }; @@ -239,6 +240,7 @@ private: void mergeAtAux(RLPStream& _out, RLP const& _replace, NibbleSlice _key, bytesConstRef _value); bytes mergeAt(RLP const& _replace, NibbleSlice _k, bytesConstRef _v, bool _inLine = false); + bytes mergeAt(RLP const& _replace, h256 const& _replaceHash, NibbleSlice _k, bytesConstRef _v, bool _inLine = false); bool deleteAtAux(RLPStream& _out, RLP const& _replace, NibbleSlice _key); bytes deleteAt(RLP const& _replace, NibbleSlice _k); @@ -295,6 +297,7 @@ private: // for the special case of the root (which is always looked up via a hash). In that case, // use forceKillNode(). void killNode(RLP const& _d) { if (_d.data().size() >= 32) forceKillNode(sha3(_d.data())); } + void killNode(RLP const& _d, h256 const& _h) { if (_d.data().size() >= 32) forceKillNode(_h); } h256 m_root; DB* m_db = nullptr; @@ -409,46 +412,59 @@ public: iterator lower_bound(bytesConstRef) const { return iterator(); } }; -// Hashed & Basic -template -class FatGenericTrieDB: public GenericTrieDB +// Hashed & Hash-key mapping +template +class FatGenericTrieDB: private SpecificTrieDB, h256> { - using Super = GenericTrieDB; + using Super = SpecificTrieDB, h256>; public: - FatGenericTrieDB(DB* _db): Super(_db), m_secure(_db) {} - FatGenericTrieDB(DB* _db, h256 _root, Verification _v = Verification::Normal) { open(_db, _root, _v); } - - void open(DB* _db, h256 _root, Verification _v = Verification::Normal) { Super::open(_db); m_secure.open(_db); setRoot(_root, _v); } + using DB = _DB; + FatGenericTrieDB(DB* _db = nullptr): Super(_db) {} + FatGenericTrieDB(DB* _db, h256 _root, Verification _v = Verification::Normal): Super(_db, _root, _v) {} - void init() { Super::init(); m_secure.init(); syncRoot(); } + using Super::init; + using Super::isNull; + using Super::isEmpty; + using Super::root; + using Super::leftOvers; + using Super::check; + using Super::open; + using Super::setRoot; - void setRoot(h256 _root, Verification _v = Verification::Normal) + std::string at(bytesConstRef _key) const { return Super::at(sha3(_key)); } + bool contains(bytesConstRef _key) { return Super::contains(sha3(_key)); } + void insert(bytesConstRef _key, bytesConstRef _value) { - if (!m_secure.isNull()) - Super::db()->removeAux(m_secure.root()); - m_secure.setRoot(_root, _v); - auto rb = Super::db()->lookupAux(m_secure.root()); - auto r = h256(rb); - Super::setRoot(r, _v); + h256 hash = sha3(_key); + Super::insert(hash, _value); + Super::db()->insertAux(hash, _key); } - h256 root() const { return m_secure.root(); } - - 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(); } + void remove(bytesConstRef _key) { Super::remove(sha3(_key)); } - h256Hash leftOvers(std::ostream* = nullptr) const { return h256Hash{}; } - bool check(bool) const { return m_secure.check(false) && Super::check(false); } + //friend class iterator; -private: - void syncRoot() + class iterator : public GenericTrieDB<_DB>::iterator { - // Root changed. Need to record the mapping so we can determine on setRoot. - Super::db()->insertAux(m_secure.root(), Super::root().ref()); - } + public: + using Super = typename GenericTrieDB<_DB>::iterator; - HashedGenericTrieDB m_secure; + iterator() { } + iterator(FatGenericTrieDB const* _trie): Super(_trie) { } + + typename Super::value_type at() const + { + auto hashed = Super::at(); + m_key = static_cast(Super::m_that)->db()->lookupAux(h256(hashed.first)); + return std::make_pair(&m_key, std::move(hashed.second)); + } + + private: + mutable bytes m_key; + }; + iterator begin() const { return iterator(); } + iterator end() const { return iterator(); } }; template using TrieDB = SpecificTrieDB, KeyType>; @@ -745,7 +761,7 @@ template void GenericTrieDB::insert(bytesConstRef _key, bytesCons std::string rv = node(m_root); assert(rv.size()); - bytes b = mergeAt(RLP(rv), NibbleSlice(_key), _value); + bytes b = mergeAt(RLP(rv), m_root, NibbleSlice(_key), _value); // mergeAt won't attempt to delete the node if it's less than 32 bytes // However, we know it's the root node and thus always hashed. @@ -765,8 +781,9 @@ template std::string GenericTrieDB::atAux(RLP const& _here, Nibbl if (_here.isEmpty() || _here.isNull()) // not found. return std::string(); - assert(_here.isList() && (_here.itemCount() == 2 || _here.itemCount() == 17)); - if (_here.itemCount() == 2) + unsigned itemCount = _here.itemCount(); + assert(_here.isList() && (itemCount == 2 || itemCount == 17)); + if (itemCount == 2) { auto k = keyOf(_here); if (_key == k && isLeaf(_here)) @@ -792,6 +809,11 @@ template std::string GenericTrieDB::atAux(RLP const& _here, Nibbl } template bytes GenericTrieDB::mergeAt(RLP const& _orig, NibbleSlice _k, bytesConstRef _v, bool _inLine) +{ + return mergeAt(_orig, sha3(_orig.data()), _k, _v, _inLine); +} + +template bytes GenericTrieDB::mergeAt(RLP const& _orig, h256 const& _origHash, NibbleSlice _k, bytesConstRef _v, bool _inLine) { #if ETH_PARANOIA tdebug << "mergeAt " << _orig << _k << sha3(_orig.data()); @@ -805,8 +827,9 @@ template bytes GenericTrieDB::mergeAt(RLP const& _orig, NibbleSli if (_orig.isEmpty()) return place(_orig, _k, _v); - assert(_orig.isList() && (_orig.itemCount() == 2 || _orig.itemCount() == 17)); - if (_orig.itemCount() == 2) + unsigned itemCount = _orig.itemCount(); + assert(_orig.isList() && (itemCount == 2 || itemCount == 17)); + if (itemCount == 2) { // pair... NibbleSlice k = keyOf(_orig); @@ -819,7 +842,7 @@ template bytes GenericTrieDB::mergeAt(RLP const& _orig, NibbleSli if (_k.contains(k) && !isLeaf(_orig)) { if (!_inLine) - killNode(_orig); + killNode(_orig, _origHash); RLPStream s(2); s.append(_orig[0]); mergeAtAux(s, _orig[1], _k.mid(k.size()), _v); @@ -851,7 +874,7 @@ template bytes GenericTrieDB::mergeAt(RLP const& _orig, NibbleSli // Kill the node. if (!_inLine) - killNode(_orig); + killNode(_orig, _origHash); // not exactly our node - delve to next level at the correct index. byte n = _k[0]; diff --git a/libethcore/Common.cpp b/libethcore/Common.cpp index 2c7601dbc..0b36ca5fa 100644 --- a/libethcore/Common.cpp +++ b/libethcore/Common.cpp @@ -37,10 +37,11 @@ namespace eth const unsigned c_protocolVersion = 60; const unsigned c_minorProtocolVersion = 2; -const unsigned c_databaseBaseVersion = 9; #if ETH_FATDB +const unsigned c_databaseBaseVersion = 10; const unsigned c_databaseVersionModifier = 1; #else +const unsigned c_databaseBaseVersion = 9; const unsigned c_databaseVersionModifier = 0; #endif diff --git a/test/libdevcrypto/trie.cpp b/test/libdevcrypto/trie.cpp index d41739a01..da90b7403 100644 --- a/test/libdevcrypto/trie.cpp +++ b/test/libdevcrypto/trie.cpp @@ -124,7 +124,9 @@ BOOST_AUTO_TEST_CASE(hex_encoded_securetrie_test) BOOST_REQUIRE(t.check(true)); BOOST_REQUIRE(ht.check(true)); BOOST_REQUIRE(ft.check(true)); - for (auto i = ft.begin(), j = t.begin(); i != ft.end() && j != t.end(); ++i, ++j) + auto i = ft.begin(); + auto j = t.begin(); + for (; i != ft.end() && j != t.end(); ++i, ++j) { BOOST_CHECK_EQUAL(i == ft.end(), j == t.end()); BOOST_REQUIRE((*i).first.toBytes() == (*j).first.toBytes()); @@ -189,7 +191,9 @@ BOOST_AUTO_TEST_CASE(trie_test_anyorder) BOOST_REQUIRE(t.check(true)); BOOST_REQUIRE(ht.check(true)); BOOST_REQUIRE(ft.check(true)); - for (auto i = ft.begin(), j = t.begin(); i != ft.end() && j != t.end(); ++i, ++j) + auto i = ft.begin(); + auto j = t.begin(); + for (; i != ft.end() && j != t.end(); ++i, ++j) { BOOST_CHECK_EQUAL(i == ft.end(), j == t.end()); BOOST_REQUIRE((*i).first.toBytes() == (*j).first.toBytes()); @@ -274,7 +278,9 @@ BOOST_AUTO_TEST_CASE(trie_tests_ordered) BOOST_REQUIRE(t.check(true)); BOOST_REQUIRE(ht.check(true)); BOOST_REQUIRE(ft.check(true)); - for (auto i = ft.begin(), j = t.begin(); i != ft.end() && j != t.end(); ++i, ++j) + auto i = ft.begin(); + auto j = t.begin(); + for (; i != ft.end() && j != t.end(); ++i, ++j) { BOOST_CHECK_EQUAL(i == ft.end(), j == t.end()); BOOST_REQUIRE((*i).first.toBytes() == (*j).first.toBytes()); @@ -558,6 +564,55 @@ BOOST_AUTO_TEST_CASE(trieStess) } } +template void perfTestTrie(char const* _name) +{ + for (size_t p = 1000; p != 1000000; p*=10) + { + MemoryDB dm; + Trie d(&dm); + d.init(); + cnote << "TriePerf " << _name << p; + std::vector keys(1000); + boost::timer t; + size_t ki = 0; + for (size_t i = 0; i < p; ++i) + { + auto k = h256::random(); + auto v = toString(i); + d.insert(k, v); + + if (i % (p / 1000) == 0) + keys[ki++] = k; + } + cnote << "Insert " << p << "values: " << t.elapsed(); + t.restart(); + for (auto k: keys) + d.at(k); + cnote << "Query 1000 values: " << t.elapsed(); + t.restart(); + size_t i = 0; + for (auto it = d.begin(); i < 1000 && it != d.end(); ++it, ++i) + *it; + cnote << "Iterate 1000 values: " << t.elapsed(); + t.restart(); + for (auto k: keys) + d.remove(k); + cnote << "Remove 1000 values:" << t.elapsed() << "\n"; + } +} + + +BOOST_AUTO_TEST_CASE(triePerf) +{ + if (test::Options::get().performance) + { + perfTestTrie, h256>>("GenericTrieDB"); + perfTestTrie, h256>>("HashedGenericTrieDB"); + perfTestTrie, h256>>("FatGenericTrieDB"); + } +} + + BOOST_AUTO_TEST_SUITE_END() From a4efee3f05b0651c25dc56baffaa83e1623b58d1 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 14 May 2015 19:50:30 +0200 Subject: [PATCH 076/157] style --- test/libdevcrypto/trie.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/libdevcrypto/trie.cpp b/test/libdevcrypto/trie.cpp index da90b7403..810876d5f 100644 --- a/test/libdevcrypto/trie.cpp +++ b/test/libdevcrypto/trie.cpp @@ -601,7 +601,6 @@ template void perfTestTrie(char const* _name) } } - BOOST_AUTO_TEST_CASE(triePerf) { if (test::Options::get().performance) @@ -612,7 +611,6 @@ BOOST_AUTO_TEST_CASE(triePerf) } } - BOOST_AUTO_TEST_SUITE_END() From 19f3a5802194f8a891ef1aa44f03a7b1573881ef Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 14 May 2015 20:08:28 +0200 Subject: [PATCH 077/157] Reduce p2p net verbosity. --- libethash-cl/ethash_cl_miner.cpp | 5 +++++ libethash-cl/ethash_cl_miner.h | 1 + libethereum/State.cpp | 4 ++-- libp2p/Common.cpp | 6 ++++++ libp2p/Common.h | 7 +++++-- libp2p/Host.cpp | 12 ++++++------ libp2p/RLPxHandshake.cpp | 28 ++++++++++++++-------------- 7 files changed, 39 insertions(+), 24 deletions(-) diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 79efbcb97..3891f2ef6 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -61,6 +61,11 @@ ethash_cl_miner::ethash_cl_miner() { } +ethash_cl_miner::~ethash_cl_miner() +{ + finish(); +} + std::string ethash_cl_miner::platform_info(unsigned _platformId, unsigned _deviceId) { std::vector platforms; diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h index 2fb192c3f..43bfa2336 100644 --- a/libethash-cl/ethash_cl_miner.h +++ b/libethash-cl/ethash_cl_miner.h @@ -30,6 +30,7 @@ public: public: ethash_cl_miner(); + ~ethash_cl_miner(); static unsigned get_num_platforms(); static unsigned get_num_devices(unsigned _platformId = 0); diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 67fa5395b..8438d3847 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -816,14 +816,14 @@ 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; - h256Hash knownUncles = _bc.allKinFrom(m_currentBlock.parentHash); + h256Hash excluded = _bc.allKinFrom(m_currentBlock.parentHash, 6); auto p = m_previousBlock.parentHash; for (unsigned gen = 0; gen < 6 && p != _bc.genesisHash() && unclesCount < 2; ++gen, p = _bc.details(p).parent) { auto us = _bc.details(p).children; assert(us.size() >= 1); // must be at least 1 child of our grandparent - it's our own parent! for (auto const& u: us) - if (!knownUncles.count(u)) // ignore any uncles/mainline blocks that we know about. + if (!excluded.count(u)) // ignore any uncles/mainline blocks that we know about. { BlockInfo ubi(_bc.block(u)); ubi.streamRLP(unclesData, WithNonce); diff --git a/libp2p/Common.cpp b/libp2p/Common.cpp index ed84f014c..ad04ca4ba 100644 --- a/libp2p/Common.cpp +++ b/libp2p/Common.cpp @@ -47,6 +47,9 @@ const char* NetTriviaDetail::name() { return EthYellow "N" EthCoal " 0"; } const char* NetAllDetail::name() { return EthYellow "N" EthCoal " A"; } const char* NetRight::name() { return EthYellow "N" EthGreen "->"; } const char* NetLeft::name() { return EthYellow "N" EthNavy "<-"; } +const char* NetP2PWarn::name() { return EthYellow "N" EthRed " X"; } +const char* NetP2PNote::name() { return EthYellow "N" EthBlue " i"; } +const char* NetP2PConnect::name() { return EthYellow "N" EthYellow " C"; } #else const char* NetWarn::name() { return EthYellow "⧎" EthRed " ✘"; } const char* NetImpolite::name() { return EthYellow "⧎" EthRed " !"; } @@ -59,6 +62,9 @@ const char* NetTriviaDetail::name() { return EthYellow "⧎" EthCoal " ◍"; } const char* NetAllDetail::name() { return EthYellow "⧎" EthCoal " ●"; } const char* NetRight::name() { return EthYellow "⧎" EthGreen "▬▶"; } const char* NetLeft::name() { return EthYellow "⧎" EthNavy "◀▬"; } +const char* NetP2PWarn::name() { return EthYellow "⧎" EthRed " ✘"; } +const char* NetP2PNote::name() { return EthYellow "⧎" EthBlue " ℹ"; } +const char* NetP2PConnect::name() { return EthYellow "⧎" EthYellow " ▢"; } #endif bool p2p::isPublicAddress(std::string const& _addressToCheck) diff --git a/libp2p/Common.h b/libp2p/Common.h index 3029bf18a..8fd330580 100644 --- a/libp2p/Common.h +++ b/libp2p/Common.h @@ -78,8 +78,8 @@ struct InvalidHostIPAddress: virtual dev::Exception {}; struct NetWarn: public LogChannel { static const char* name(); static const int verbosity = 0; }; struct NetNote: public LogChannel { static const char* name(); static const int verbosity = 1; }; -struct NetImpolite: public LogChannel { static const char* name(); static const int verbosity = 1; }; -struct NetMessageSummary: public LogChannel { static const char* name(); static const int verbosity = 2; }; +struct NetImpolite: public LogChannel { static const char* name(); static const int verbosity = 2; }; +struct NetMessageSummary: public LogChannel { static const char* name(); static const int verbosity = 3; }; struct NetConnect: public LogChannel { static const char* name(); static const int verbosity = 10; }; struct NetMessageDetail: public LogChannel { static const char* name(); static const int verbosity = 5; }; struct NetTriviaSummary: public LogChannel { static const char* name(); static const int verbosity = 10; }; @@ -87,6 +87,9 @@ struct NetTriviaDetail: public LogChannel { static const char* name(); static co struct NetAllDetail: public LogChannel { static const char* name(); static const int verbosity = 13; }; struct NetRight: public LogChannel { static const char* name(); static const int verbosity = 14; }; struct NetLeft: public LogChannel { static const char* name(); static const int verbosity = 15; }; +struct NetP2PWarn: public LogChannel { static const char* name(); static const int verbosity = 2; }; +struct NetP2PNote: public LogChannel { static const char* name(); static const int verbosity = 6; }; +struct NetP2PConnect: public LogChannel { static const char* name(); static const int verbosity = 10; }; enum PacketType { diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 9b5a6dca7..2f139fd3d 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -244,7 +244,7 @@ void Host::startPeerSession(Public const& _id, RLP const& _rlp, RLPXFrameIO* _io m_sessions[_id] = ps; } - clog(NetNote) << "p2p.host.peer.register" << _id; + clog(NetP2PNote) << "p2p.host.peer.register" << _id; StructuredLogger::p2pConnected(_id.abridged(), ps->m_peer->endpoint, ps->m_peer->m_lastConnected, clientVersion, peerCount()); } @@ -252,7 +252,7 @@ void Host::onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e) { if (_e == NodeEntryAdded) { - clog(NetNote) << "p2p.host.nodeTable.events.nodeEntryAdded " << _n; + clog(NetP2PNote) << "p2p.host.nodeTable.events.nodeEntryAdded " << _n; // only add iff node is in node table if (Node n = m_nodeTable->node(_n)) { @@ -268,7 +268,7 @@ void Host::onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e) { p.reset(new Peer(n)); m_peers[_n] = p; - clog(NetNote) << "p2p.host.peers.events.peerAdded " << _n << p->endpoint; + clog(NetP2PNote) << "p2p.host.peers.events.peerAdded " << _n << p->endpoint; } } if (peerSlotsAvailable(Egress)) @@ -277,7 +277,7 @@ void Host::onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e) } else if (_e == NodeEntryDropped) { - clog(NetNote) << "p2p.host.nodeTable.events.NodeEntryDropped " << _n; + clog(NetP2PNote) << "p2p.host.nodeTable.events.NodeEntryDropped " << _n; RecursiveGuard l(x_sessions); m_peers.erase(_n); } @@ -647,14 +647,14 @@ void Host::startedWorking() runAcceptor(); } else - clog(NetNote) << "p2p.start.notice id:" << id() << "TCP Listen port is invalid or unavailable."; + clog(NetP2PNote) << "p2p.start.notice id:" << id() << "TCP Listen port is invalid or unavailable."; shared_ptr nodeTable(new NodeTable(m_ioService, m_alias, NodeIPEndpoint(bi::address::from_string(listenAddress()), listenPort(), listenPort()))); nodeTable->setEventHandler(new HostNodeTableHandler(*this)); m_nodeTable = nodeTable; restoreNetwork(&m_restoreNetwork); - clog(NetNote) << "p2p.started id:" << id(); + clog(NetP2PNote) << "p2p.started id:" << id(); run(boost::system::error_code()); } diff --git a/libp2p/RLPxHandshake.cpp b/libp2p/RLPxHandshake.cpp index 8566b4f50..65116cd58 100644 --- a/libp2p/RLPxHandshake.cpp +++ b/libp2p/RLPxHandshake.cpp @@ -30,7 +30,7 @@ using namespace CryptoPP; void RLPXHandshake::writeAuth() { - clog(NetConnect) << "p2p.connect.egress sending auth to " << m_socket->remoteEndpoint(); + clog(NetP2PConnect) << "p2p.connect.egress sending auth to " << m_socket->remoteEndpoint(); m_auth.resize(Signature::size + h256::size + Public::size + h256::size + 1); bytesRef sig(&m_auth[0], Signature::size); bytesRef hepubk(&m_auth[Signature::size], h256::size); @@ -56,7 +56,7 @@ void RLPXHandshake::writeAuth() void RLPXHandshake::writeAck() { - clog(NetConnect) << "p2p.connect.ingress sending ack to " << m_socket->remoteEndpoint(); + clog(NetP2PConnect) << "p2p.connect.ingress sending ack to " << m_socket->remoteEndpoint(); m_ack.resize(Public::size + h256::size + 1); bytesRef epubk(&m_ack[0], Public::size); bytesRef nonce(&m_ack[Public::size], h256::size); @@ -74,7 +74,7 @@ void RLPXHandshake::writeAck() void RLPXHandshake::readAuth() { - clog(NetConnect) << "p2p.connect.ingress recving auth from " << m_socket->remoteEndpoint(); + clog(NetP2PConnect) << "p2p.connect.ingress recving auth from " << m_socket->remoteEndpoint(); m_authCipher.resize(307); auto self(shared_from_this()); ba::async_read(m_socket->ref(), ba::buffer(m_authCipher, 307), [this, self](boost::system::error_code ec, std::size_t) @@ -95,13 +95,13 @@ void RLPXHandshake::readAuth() m_remoteEphemeral = recover(*(Signature*)sig.data(), sharedSecret ^ m_remoteNonce); if (sha3(m_remoteEphemeral) != *(h256*)hepubk.data()) - clog(NetConnect) << "p2p.connect.ingress auth failed (invalid: hash mismatch) for" << m_socket->remoteEndpoint(); + clog(NetP2PConnect) << "p2p.connect.ingress auth failed (invalid: hash mismatch) for" << m_socket->remoteEndpoint(); transition(); } else { - clog(NetConnect) << "p2p.connect.ingress recving auth decrypt failed for" << m_socket->remoteEndpoint(); + clog(NetP2PConnect) << "p2p.connect.ingress recving auth decrypt failed for" << m_socket->remoteEndpoint(); m_nextState = Error; transition(); } @@ -110,7 +110,7 @@ void RLPXHandshake::readAuth() void RLPXHandshake::readAck() { - clog(NetConnect) << "p2p.connect.egress recving ack from " << m_socket->remoteEndpoint(); + clog(NetP2PConnect) << "p2p.connect.egress recving ack from " << m_socket->remoteEndpoint(); m_ackCipher.resize(210); auto self(shared_from_this()); ba::async_read(m_socket->ref(), ba::buffer(m_ackCipher, 210), [this, self](boost::system::error_code ec, std::size_t) @@ -125,7 +125,7 @@ void RLPXHandshake::readAck() } else { - clog(NetConnect) << "p2p.connect.egress recving ack decrypt failed for " << m_socket->remoteEndpoint(); + clog(NetP2PConnect) << "p2p.connect.egress recving ack decrypt failed for " << m_socket->remoteEndpoint(); m_nextState = Error; transition(); } @@ -138,9 +138,9 @@ void RLPXHandshake::error() auto connected = m_socket->isConnected(); if (connected && !m_socket->remoteEndpoint().address().is_unspecified()) - clog(NetConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Failed)"; + clog(NetP2PConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Failed)"; else - clog(NetConnect) << "Handshake Failed (Connection reset by peer)"; + clog(NetP2PConnect) << "Handshake Failed (Connection reset by peer)"; m_socket->close(); if (m_io != nullptr) @@ -151,7 +151,7 @@ void RLPXHandshake::transition(boost::system::error_code _ech) { if (_ech || m_nextState == Error || m_cancel) { - clog(NetConnect) << "Handshake Failed (I/O Error:" << _ech.message() << ")"; + clog(NetP2PConnect) << "Handshake Failed (I/O Error:" << _ech.message() << ")"; return error(); } @@ -175,7 +175,7 @@ void RLPXHandshake::transition(boost::system::error_code _ech) else if (m_nextState == WriteHello) { m_nextState = ReadHello; - clog(NetConnect) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "sending capabilities handshake"; + clog(NetP2PConnect) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "sending capabilities handshake"; /// This pointer will be freed if there is an error otherwise /// it will be passed to Host which will take ownership. @@ -220,7 +220,7 @@ void RLPXHandshake::transition(boost::system::error_code _ech) return; } - clog(NetNote) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "recvd hello header"; + clog(NetP2PNote) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "recvd hello header"; /// check frame size bytes& header = m_handshakeInBuffer; @@ -228,7 +228,7 @@ void RLPXHandshake::transition(boost::system::error_code _ech) if (frameSize > 1024) { // all future frames: 16777216 - clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame is too large" << frameSize; + clog(NetP2PWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame is too large" << frameSize; m_nextState = Error; transition(); return; @@ -279,7 +279,7 @@ void RLPXHandshake::transition(boost::system::error_code _ech) if (!_ec) { if (!m_socket->remoteEndpoint().address().is_unspecified()) - clog(NetConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Timeout)"; + clog(NetP2PConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Timeout)"; cancel(); } }); From b7683a8c65225b6bd2af00e924e2cfe1bf0ff927 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 14 May 2015 20:11:56 +0200 Subject: [PATCH 078/157] fixed m_pubkDiscoverPings guard --- libp2p/NodeTable.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libp2p/NodeTable.cpp b/libp2p/NodeTable.cpp index b51ba8211..bf056c52f 100644 --- a/libp2p/NodeTable.cpp +++ b/libp2p/NodeTable.cpp @@ -95,7 +95,7 @@ shared_ptr NodeTable::addNode(Node const& _node, NodeRelation _relati { DEV_GUARDED(x_nodes) clog(NodeTableConnect) << "Sending public key discovery Ping to" << (bi::udp::endpoint)_node.endpoint << "(Advertising:" << (bi::udp::endpoint)m_node.endpoint << ")"; - DEV_GUARDED(x_pubkDiscoverPings); + DEV_GUARDED(x_pubkDiscoverPings) m_pubkDiscoverPings[_node.endpoint.address] = std::chrono::steady_clock::now(); ping(_node.endpoint); return move(shared_ptr()); From 1958a7a46942f9543589467a863fcb50277f8a49 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 14 May 2015 20:55:57 +0200 Subject: [PATCH 079/157] Skip second nonce check on import --- libethereum/BlockChain.cpp | 2 +- libethereum/State.cpp | 8 ++++---- libethereum/State.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 7c03bc24f..712a1e1ba 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -639,7 +639,7 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import } try { - State canary(_db, *this, bi.hash()); + State canary(_db, *this, bi.hash(), ImportRequirements::DontHave); } catch (...) { diff --git a/libethereum/State.cpp b/libethereum/State.cpp index f5739aadb..1a73177d5 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -114,7 +114,7 @@ State::State(OverlayDB const& _db, BaseState _bs, Address _coinbaseAddress): paranoia("end of normal construction.", true); } -State::State(OverlayDB const& _db, BlockChain const& _bc, h256 _h): +State::State(OverlayDB const& _db, BlockChain const& _bc, h256 _h, ImportRequirements::value _ir): m_db(_db), m_state(&m_db), m_blockReward(c_blockReward) @@ -136,18 +136,18 @@ State::State(OverlayDB const& _db, BlockChain const& _bc, h256 _h): // 1. Start at parent's end state (state root). BlockInfo bip; bip.populate(_bc.block(bi.parentHash)); - sync(_bc, bi.parentHash, bip); + sync(_bc, bi.parentHash, bip, _ir); // 2. Enact the block's transactions onto this state. m_ourAddress = bi.coinbaseAddress; - enact(&b, _bc); + enact(&b, _bc, _ir); } else { // Genesis required: // We know there are no transactions, so just populate directly. m_state.init(); - sync(_bc, _h, bi); + sync(_bc, _h, bi, _ir); } } diff --git a/libethereum/State.h b/libethereum/State.h index a11812c6f..d9fc9d2b5 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -118,7 +118,7 @@ public: explicit State(OverlayDB const& _db, BaseState _bs = BaseState::PreExisting, Address _coinbaseAddress = Address()); /// Construct state object from arbitrary point in blockchain. - State(OverlayDB const& _db, BlockChain const& _bc, h256 _hash); + State(OverlayDB const& _db, BlockChain const& _bc, h256 _hash, ImportRequirements::value _ir = ImportRequirements::Default); /// Copy state object. State(State const& _s); From 648a83f0fc9b700096498f862395bd9b9671b8e6 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 14 May 2015 21:53:59 +0200 Subject: [PATCH 080/157] Stricter interface for EthashAux::light() --- eth/main.cpp | 2 +- ethminer/main.cpp | 2 +- libethcore/EthashAux.cpp | 5 ----- libethcore/EthashAux.h | 1 - test/libethcore/dagger.cpp | 8 ++++---- 5 files changed, 6 insertions(+), 12 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index e352cd53a..dc130e296 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -866,7 +866,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(bi)->data()) << endl; + cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(bi.seedHash())->data()) << endl; exit(0); } catch (...) diff --git a/ethminer/main.cpp b/ethminer/main.cpp index 33c2e7c80..732d49dee 100644 --- a/ethminer/main.cpp +++ b/ethminer/main.cpp @@ -441,7 +441,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(bi)->data()) << endl; + cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(bi.seedHash())->data()) << endl; exit(0); } catch (...) diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index 4f29a6516..aeacf325a 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -105,11 +105,6 @@ void EthashAux::killCache(h256 const& _s) m_lights.erase(_s); } -EthashAux::LightType EthashAux::light(BlockInfo const& _header) -{ - return light(_header.seedHash()); -} - EthashAux::LightType EthashAux::light(h256 const& _seedHash) { RecursiveGuard l(get()->x_lights); diff --git a/libethcore/EthashAux.h b/libethcore/EthashAux.h index 2a4060e78..64501e37b 100644 --- a/libethcore/EthashAux.h +++ b/libethcore/EthashAux.h @@ -65,7 +65,6 @@ public: static uint64_t number(h256 const& _seedHash); static uint64_t cacheSize(BlockInfo const& _header); - static LightType light(BlockInfo const& _header); static LightType light(h256 const& _seedHash); static const uint64_t NotGenerating = (uint64_t)-1; diff --git a/test/libethcore/dagger.cpp b/test/libethcore/dagger.cpp index 4faf0a283..59770373d 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()->light(header)->size, cacheSize); - BOOST_REQUIRE_EQUAL(sha3(EthashAux::get()->light(header)->data()), cacheHash); + BOOST_REQUIRE_EQUAL(EthashAux::get()->light(header.seedHash())->size, cacheSize); + BOOST_REQUIRE_EQUAL(sha3(EthashAux::get()->light(header.seedHash())->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)->data()), fullHash); + BOOST_REQUIRE_EQUAL(EthashAux::get()->full(header.seedHash())->size(), fullSize); + BOOST_REQUIRE_EQUAL(sha3(EthashAux::get()->full(header.seedHash())->data()), fullHash); #endif h256 result(o["result"].get_str()); From 38bf18de816a6d62fcfae5c656b72633eeaa66cb Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Thu, 14 May 2015 21:59:36 +0200 Subject: [PATCH 081/157] fix in chain uncle tests --- test/libethereum/blockchain.cpp | 35 ++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/test/libethereum/blockchain.cpp b/test/libethereum/blockchain.cpp index 824eafe26..191b94cc3 100644 --- a/test/libethereum/blockchain.cpp +++ b/test/libethereum/blockchain.cpp @@ -204,6 +204,20 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) blObj["transactions"] = writeTransactionsToJson(txList); BlockInfo current_BlockHeader = state.info(); + + RLPStream uncleStream; + uncleStream.appendList(vBiUncles.size()); + for (unsigned i = 0; i < vBiUncles.size(); ++i) + { + RLPStream uncleRlp; + vBiUncles[i].streamRLP(uncleRlp, WithNonce); + uncleStream.appendRaw(uncleRlp.out()); + } + + // update unclehash in case of invalid uncles + current_BlockHeader.sha3Uncles = sha3(uncleStream.out()); + updatePoW(current_BlockHeader); + if (blObj.count("blockHeader")) overwriteBlockHeader(current_BlockHeader, blObj); @@ -223,15 +237,6 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) txStream.appendRaw(txrlp.out()); } - RLPStream uncleStream; - uncleStream.appendList(vBiUncles.size()); - for (unsigned i = 0; i < vBiUncles.size(); ++i) - { - RLPStream uncleRlp; - vBiUncles[i].streamRLP(uncleRlp, WithNonce); - uncleStream.appendRaw(uncleRlp.out()); - } - RLPStream block2 = createFullBlockFromHeader(current_BlockHeader, txStream.out(), uncleStream.out()); blObj["rlp"] = toHex(block2.out(), 2, HexPrefix::Add); @@ -497,14 +502,20 @@ mArray importUncles(mObject const& blObj, vector& vBiUncles, vector Date: Thu, 14 May 2015 22:56:19 +0200 Subject: [PATCH 082/157] update gas Pricer tests --- test/libethereum/gaspricer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/libethereum/gaspricer.cpp b/test/libethereum/gaspricer.cpp index 577d217e8..68a55ab42 100644 --- a/test/libethereum/gaspricer.cpp +++ b/test/libethereum/gaspricer.cpp @@ -115,26 +115,26 @@ BOOST_AUTO_TEST_CASE(basicGasPricer_notxs) BOOST_AUTO_TEST_CASE(basicGasPricer_highGasUsage_LowestPrio) { - dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Lowest, 15731292650, 10000000000000); + dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Lowest, 15731282021, 10000000000000); } BOOST_AUTO_TEST_CASE(basicGasPricer_highGasUsage_LowPrio) { - dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Low, 15731292650, 15734152261884); + dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Low, 15731282021, 15734152261884); } BOOST_AUTO_TEST_CASE(basicGasPricer_highGasUsage_MediumPrio) { - dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Medium, 15731292650, 20000000000000); + dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Medium, 15731282021, 20000000000000); } BOOST_AUTO_TEST_CASE(basicGasPricer_highGasUsage_HighPrio) { - dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::High, 15731292650, 24265847738115); + dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::High, 15731282021, 24265847738115); } BOOST_AUTO_TEST_CASE(basicGasPricer_highGasUsage_HighestPrio) { - dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Highest, 15731292650, 30000000000000); + dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Highest, 15731282021, 30000000000000); } BOOST_AUTO_TEST_SUITE_END() From 3881b160d64938d840c9a3cdcbba31aee9f15985 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 15 May 2015 11:26:19 +0200 Subject: [PATCH 083/157] Display gas estimation as annotation --- mix/CodeModel.cpp | 8 ++-- mix/CodeModel.h | 6 ++- mix/qml/Application.qml | 15 ++++++ mix/qml/CodeEditorView.qml | 9 +++- mix/qml/WebCodeEditor.qml | 10 ++-- mix/qml/html/cm/solarized.css | 6 ++- mix/qml/html/codeeditor.js | 87 +++++++++++++++++++++++++++++++---- 7 files changed, 117 insertions(+), 24 deletions(-) diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index ecdb46be3..d9262586b 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -189,7 +189,6 @@ CodeModel::CodeModel(): qRegisterMetaType("QContractDefinition*"); qRegisterMetaType("QFunctionDefinition*"); qRegisterMetaType("QVariableDeclaration*"); - //qRegisterMetaType("GasMap"); qmlRegisterType("org.ethereum.qml", 1, 0, "QFunctionDefinition"); qmlRegisterType("org.ethereum.qml", 1, 0, "QVariableDeclaration"); } @@ -325,7 +324,6 @@ void CodeModel::gasEstimation(solidity::CompilerStack const& _cs) m_gasCostsMaps.clear(); for (std::string n: _cs.getContractNames()) { - ContractDefinition const& contractDefinition = _cs.getContractDefinition(n); QString sourceName = QString::fromStdString(*contractDefinition.getLocation().sourceName); @@ -344,7 +342,9 @@ void CodeModel::gasEstimation(solidity::CompilerStack const& _cs) { SourceLocation location = gasIte->first->getLocation(); GasMeter::GasConsumption cost = gasIte->second; - GasMap* gas = new GasMap(location.start, location.end, (new QBigInt(cost.value))->value()); + std::stringstream v; + v << cost.value; + GasMap* gas = new GasMap(location.start, location.end, QString::fromStdString(v.str()), gasIte->second.isInfinite); m_gasCostsMaps.find(sourceName).value().push_back(QVariant::fromValue(gas)); } } @@ -355,8 +355,6 @@ QVariantList CodeModel::gasCostByDocumentId(QString const& _documentId) const if (m_gasCostsMaps.contains(_documentId)) { auto sourceMapIter = m_gasCostsMaps.find(_documentId); - int gg = sourceMapIter.value().size(); - Q_UNUSED(gg); return sourceMapIter.value(); } else diff --git a/mix/CodeModel.h b/mix/CodeModel.h index a1a2c29ec..b28c5f6c6 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -134,17 +134,19 @@ class GasMap: public QObject Q_PROPERTY(int start MEMBER m_start CONSTANT) Q_PROPERTY(int end MEMBER m_end CONSTANT) Q_PROPERTY(QString gas MEMBER m_gas CONSTANT) + Q_PROPERTY(bool isInfinite MEMBER m_isInfinite CONSTANT) public: - GasMap(int _start, int _end, QString _gas): m_start(_start), m_end(_end), m_gas(_gas) {} + GasMap(int _start, int _end, QString _gas, bool _isInfinite): m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite) {} int m_start; int m_end; QString m_gas; + bool m_isInfinite; }; using SourceMaps = QMap; //by source id -using GasCostsMaps = QMap*/>; //gas cost by contract name +using GasCostsMaps = QMap; //gas cost by contract name /// Code compilation model. Compiles contracts in background an provides compiled contract data class CodeModel: public QObject diff --git a/mix/qml/Application.qml b/mix/qml/Application.qml index fe62efe12..161f7141a 100644 --- a/mix/qml/Application.qml +++ b/mix/qml/Application.qml @@ -116,6 +116,10 @@ ApplicationWindow { MenuSeparator {} MenuItem { action: toggleAssemblyDebuggingAction } } + Menu { + title: qsTr("Tools") + MenuItem { action: gasEstimationAction } + } Menu { title: qsTr("Windows") MenuItem { action: openNextDocumentAction } @@ -409,4 +413,15 @@ ApplicationWindow { mainContent.codeEditor.goToCompilationError(); } } + + Action { + id: gasEstimationAction + text: qsTr("Display gas estimation") + shortcut: "Ctrl+G" + checkable: true + onTriggered: + { + mainContent.codeEditor.displayGasEstimation(checked); + } + } } diff --git a/mix/qml/CodeEditorView.qml b/mix/qml/CodeEditorView.qml index 08bb072f5..08610a8e1 100644 --- a/mix/qml/CodeEditorView.qml +++ b/mix/qml/CodeEditorView.qml @@ -168,6 +168,13 @@ Item { editors.itemAt(i).item.setFontSize(size); } + function displayGasEstimation(checked) + { + var editor = getEditor(currentDocumentId); + if (editor) + editor.displayGasEstimation(checked); + } + Component.onCompleted: projectModel.codeEditor = codeEditorView; Connections { @@ -180,7 +187,7 @@ Item { var gasCosts = codeModel.gasCostByDocumentId(currentDocumentId); var editor = getEditor(currentDocumentId); if (editor) - editor.displayGasCosts(gasCosts); + editor.setGasCosts(gasCosts); } } diff --git a/mix/qml/WebCodeEditor.qml b/mix/qml/WebCodeEditor.qml index a2602304a..0d681d79c 100644 --- a/mix/qml/WebCodeEditor.qml +++ b/mix/qml/WebCodeEditor.qml @@ -83,12 +83,14 @@ Item { editorBrowser.runJavaScript("setFontSize(" + size + ")", function(result) {}); } - function displayGasCosts(gasCosts) { + function setGasCosts(gasCosts) { + if (initialized && editorBrowser) + editorBrowser.runJavaScript("setGasCosts('" + JSON.stringify(gasCosts) + "')", function(result) {}); + } - //console.log(gasCosts); - //console.log(JSON.stringify(gasCosts)); + function displayGasEstimation(show) { if (initialized && editorBrowser) - editorBrowser.runJavaScript("displayGasCosts('" + JSON.stringify(gasCosts) + "')", function(result) {}); + editorBrowser.runJavaScript("displayGasEstimation('" + show + "')", function(result) {}); } Clipboard diff --git a/mix/qml/html/cm/solarized.css b/mix/qml/html/cm/solarized.css index 046042450..1d298b990 100644 --- a/mix/qml/html/cm/solarized.css +++ b/mix/qml/html/cm/solarized.css @@ -190,6 +190,8 @@ view-port span.CodeMirror-selectedtext { color: #586e75 !important; } -.gasCost { - background: #b58900 !important; +/* Gas Costs */ +.CodeMirror-gasCosts { + border-bottom: double 1px #2aa198; } + diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index cc5e9a28c..3e1a54958 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -3,7 +3,7 @@ var editor = CodeMirror(document.body, { //styleActiveLine: true, matchBrackets: true, autofocus: true, - gutters: ["CodeMirror-linenumbers", "breakpoints", "gasCost"], + gutters: ["CodeMirror-linenumbers", "breakpoints"], autoCloseBrackets: true, styleSelectedText: true }); @@ -207,22 +207,89 @@ makeGasCostMarker = function(value) { var marker = document.createElement("div"); marker.style.color = "#822"; marker.innerHTML = value; + marker.className = "CodeMirror-errorannotation-context"; return marker; }; -displayGasCosts = function(gasCosts) +var gasCosts = null; +setGasCosts = function(_gasCosts) { - gasCosts = JSON.parse(gasCosts); - for (var i in gasCosts) + gasCosts = JSON.parse(_gasCosts); + + if (showGasEstimation) + { + displayGasEstimation(false); + displayGasEstimation(true); + } +} + +var showGasEstimation = false; +var gasMarkText = []; +var gasMarkRef = {}; +displayGasEstimation = function(show) +{ + show = JSON.parse(show); + showGasEstimation = show; + if (show) + { + var maxGas = 20000; + var step = colorGradient.length / maxGas; // 20000 max gas + gasMarkRef = []; + gasMarkRef = {}; + for (var i in gasCosts) + { + if (gasCosts[i].gas !== "0") + { + var color; + var colorIndex = Math.round(step * gasCosts[i].gas); + if (gasCosts[i].isInfinite || colorIndex > colorGradient.length) + color = colorGradient[colorGradient.length - 1]; + else + color = colorGradient[colorIndex]; + var className = "CodeMirror-gasCosts" + i; + var line = editor.posFromIndex(gasCosts[i].start) + gasMarkText.push(editor.markText(line, editor.posFromIndex(gasCosts[i].end), { inclusiveLeft: true, inclusiveRight: true, handleMouseEvents: true, className: className, css: "background-color:" + color })); + gasMarkRef[className] = { line: line.line, value: gasCosts[i] }; + } + } + CodeMirror.on(editor.getWrapperElement(), "mouseover", listenMouseOver); + } + else { - var line = editor.posFromIndex(gasCosts[i].start); - console.log("___________") - console.log(line.line); - console.log(gasCosts[i].start); - //editor.setGutterMarker(line.line, "gasCost", makeGasCostMarker(gasCosts[i].gas)); - editor.markText(editor.posFromIndex(gasCosts[i].start), editor.posFromIndex(gasCosts[i].end), { className: "gasCost" }); + CodeMirror.off(editor.getWrapperElement(), "mouseover", listenMouseOver); + for (var k in gasMarkText) + gasMarkText[k].clear(); + if (gasAnnotation) + { + gasAnnotation.clear(); + gasAnnotation = null; + } + } +} + +var gasAnnotation; +function listenMouseOver(e) +{ + var node = e.target || e.srcElement; + if (node) { + if (!gasAnnotation && node.className && node.className.indexOf("CodeMirror-gasCosts") !== -1) + { + if (gasAnnotation) + gasAnnotation.clear(); + var cl = node.className.split(" ")[1]; + var gasTitle = gasMarkRef[cl].value.isInfinite ? "infinite" : gasMarkRef[cl].value.gas; + gasTitle = gasTitle + " gas"; + gasAnnotation = editor.addLineWidget(gasMarkRef[cl].line + 1, makeGasCostMarker(gasTitle), { coverGutter: false, above: true }); + } + else if (gasAnnotation) + { + gasAnnotation.clear(); + gasAnnotation = null; + } } } +// blue => red ["#1515ED", "#1714EA", "#1914E8", "#1B14E6", "#1D14E4", "#1F14E2", "#2214E0", "#2414DE", "#2614DC", "#2813DA", "#2A13D8", "#2D13D6", "#2F13D4", "#3113D2", "#3313D0", "#3513CE", "#3713CC", "#3A12CA", "#3C12C8", "#3E12C6", "#4012C4", "#4212C2", "#4512C0", "#4712BE", "#4912BC", "#4B11BA", "#4D11B8", "#4F11B6", "#5211B4", "#5411B2", "#5611B0", "#5811AE", "#5A11AC", "#5D11AA", "#5F10A7", "#6110A5", "#6310A3", "#6510A1", "#67109F", "#6A109D", "#6C109B", "#6E1099", "#700F97", "#720F95", "#750F93", "#770F91", "#790F8F", "#7B0F8D", "#7D0F8B", "#7F0F89", "#820E87", "#840E85", "#860E83", "#880E81", "#8A0E7F", "#8D0E7D", "#8F0E7B", "#910E79", "#930D77", "#950D75", "#970D73", "#9A0D71", "#9C0D6F", "#9E0D6D", "#A00D6B", "#A20D69", "#A50D67", "#A70C64", "#A90C62", "#AB0C60", "#AD0C5E", "#AF0C5C", "#B20C5A", "#B40C58", "#B60C56", "#B80B54", "#BA0B52", "#BD0B50", "#BF0B4E", "#C10B4C", "#C30B4A", "#C50B48", "#C70B46", "#CA0A44", "#CC0A42", "#CE0A40", "#D00A3E", "#D20A3C", "#D50A3A", "#D70A38", "#D90A36", "#DB0934", "#DD0932", "#DF0930", "#E2092E", "#E4092C", "#E6092A", "#E80928", "#EA0926", "#ED0924"] +/* green => red */ var colorGradient = ["#429C27", "#439A26", "#449926", "#469726", "#479626", "#489525", "#4A9325", "#4B9225", "#4D9025", "#4E8F25", "#4F8E24", "#518C24", "#528B24", "#548924", "#558824", "#568723", "#588523", "#598423", "#5B8223", "#5C8122", "#5D8022", "#5F7E22", "#607D22", "#627B22", "#637A21", "#647921", "#667721", "#677621", "#697421", "#6A7320", "#6B7220", "#6D7020", "#6E6F20", "#706E20", "#716C1F", "#726B1F", "#74691F", "#75681F", "#76671E", "#78651E", "#79641E", "#7B621E", "#7C611E", "#7D601D", "#7F5E1D", "#805D1D", "#825B1D", "#835A1D", "#84591C", "#86571C", "#87561C", "#89541C", "#8A531B", "#8B521B", "#8D501B", "#8E4F1B", "#904D1B", "#914C1A", "#924B1A", "#94491A", "#95481A", "#97461A", "#984519", "#994419", "#9B4219", "#9C4119", "#9E4019", "#9F3E18", "#A03D18", "#A23B18", "#A33A18", "#A43917", "#A63717", "#A73617", "#A93417", "#AA3317", "#AB3216", "#AD3016", "#AE2F16", "#B02D16", "#B12C16", "#B22B15", "#B42915", "#B52815", "#B72615", "#B82514", "#B92414", "#BB2214", "#BC2114", "#BE1F14", "#BF1E13", "#C01D13", "#C21B13", "#C31A13", "#C51813", "#C61712", "#C71612", "#C91412", "#CA1312", "#CC1212"] editor.setOption("extraKeys", extraKeys); From 32f57c6c25911022bbeced63d0a51047f9042099 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 15 May 2015 11:46:32 +0200 Subject: [PATCH 084/157] Disable test. --- test/libsolidity/SolidityOptimizer.cpp | 27 ++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index ce43887e1..e8cc2d5b5 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -884,18 +884,21 @@ 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); -} +// ****************************** +// DISABLED DUE TO FAILURE ON OSX +// ****************************** +//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) { From 9357e47a8392fc227cde74ba9c95e3c058c869eb Mon Sep 17 00:00:00 2001 From: subtly Date: Fri, 15 May 2015 11:50:21 +0200 Subject: [PATCH 085/157] Update gas limit modulation. --- libethcore/BlockInfo.cpp | 5 ++++- libwhisper/WhisperPeer.cpp | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index eb64593af..e70b16753 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -228,7 +228,10 @@ u256 BlockInfo::selectGasLimit(BlockInfo const& _parent) const return c_genesisGasLimit; else // target minimum of 3141592 - return max(max(c_minGasLimit, 3141592), _parent.gasLimit - _parent.gasLimit / c_gasLimitBoundDivisor + 1 + (_parent.gasUsed * 6 / 5) / c_gasLimitBoundDivisor); + if (_parent.gasLimit < c_genesisGasLimit) + return min(c_genesisGasLimit, _parent.gasLimit + _parent.gasLimit / c_gasLimitBoundDivisor - 1); + else + return max(c_genesisGasLimit, _parent.gasLimit - _parent.gasLimit / c_gasLimitBoundDivisor + 1 + (_parent.gasUsed * 6 / 5) / c_gasLimitBoundDivisor); } u256 BlockInfo::calculateDifficulty(BlockInfo const& _parent) const diff --git a/libwhisper/WhisperPeer.cpp b/libwhisper/WhisperPeer.cpp index 9bef25140..5ac538171 100644 --- a/libwhisper/WhisperPeer.cpp +++ b/libwhisper/WhisperPeer.cpp @@ -68,8 +68,7 @@ bool WhisperPeer::interpret(unsigned _id, RLP const& _r) { unsigned n = 0; for (auto i: _r) - if (n++) - host()->inject(Envelope(i), this); + host()->inject(Envelope(i), this); break; } default: From dc054d7b53ef74274216257d86cd68e33d906cdf Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 15 May 2015 12:01:20 +0200 Subject: [PATCH 086/157] bug fix --- mix/CodeModel.cpp | 1 - mix/qml/CodeEditorView.qml | 1 + mix/qml/WebCodeEditor.qml | 5 +++++ mix/qml/html/codeeditor.js | 19 +++++++++++++------ 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index d9262586b..71a2f0eba 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -43,7 +43,6 @@ #include "CodeHighlighter.h" #include "FileIo.h" #include "CodeModel.h" -#include "QBigInt.h" using namespace dev::mix; diff --git a/mix/qml/CodeEditorView.qml b/mix/qml/CodeEditorView.qml index 08610a8e1..a5f8cd233 100644 --- a/mix/qml/CodeEditorView.qml +++ b/mix/qml/CodeEditorView.qml @@ -288,6 +288,7 @@ Item { messageDialog.doc = editorListModel.get(index); messageDialog.open(); } + loader.item.displayGasEstimation(gasEstimationAction.checked); } } Component.onCompleted: { diff --git a/mix/qml/WebCodeEditor.qml b/mix/qml/WebCodeEditor.qml index 0d681d79c..562c9716b 100644 --- a/mix/qml/WebCodeEditor.qml +++ b/mix/qml/WebCodeEditor.qml @@ -144,7 +144,12 @@ Item { function compilationComplete() { if (editorBrowser) + { editorBrowser.runJavaScript("compilationComplete()", function(result) { }); + parent.displayGasEstimation(gasEstimationAction.checked); + } + + } function compilationError(error, sourceName) diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index 3e1a54958..7d68f4032 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -216,25 +216,26 @@ setGasCosts = function(_gasCosts) { gasCosts = JSON.parse(_gasCosts); - if (showGasEstimation) + if (showingGasEstimation) { displayGasEstimation(false); displayGasEstimation(true); } } -var showGasEstimation = false; +var showingGasEstimation = false; var gasMarkText = []; var gasMarkRef = {}; displayGasEstimation = function(show) { show = JSON.parse(show); - showGasEstimation = show; + showingGasEstimation = show; if (show) { var maxGas = 20000; var step = colorGradient.length / maxGas; // 20000 max gas - gasMarkRef = []; + clearGasMark(); + gasMarkText = []; gasMarkRef = {}; for (var i in gasCosts) { @@ -257,8 +258,7 @@ displayGasEstimation = function(show) else { CodeMirror.off(editor.getWrapperElement(), "mouseover", listenMouseOver); - for (var k in gasMarkText) - gasMarkText[k].clear(); + clearGasMark(); if (gasAnnotation) { gasAnnotation.clear(); @@ -267,6 +267,13 @@ displayGasEstimation = function(show) } } +function clearGasMark() +{ + if (gasMarkText) + for (var k in gasMarkText) + gasMarkText[k].clear(); +} + var gasAnnotation; function listenMouseOver(e) { From bc7e909eabdf5a860bf19b5b5633be6ac5d50dcb Mon Sep 17 00:00:00 2001 From: subtly Date: Fri, 15 May 2015 12:15:55 +0200 Subject: [PATCH 087/157] reverse unrelated code --- libwhisper/WhisperPeer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libwhisper/WhisperPeer.cpp b/libwhisper/WhisperPeer.cpp index 5ac538171..9bef25140 100644 --- a/libwhisper/WhisperPeer.cpp +++ b/libwhisper/WhisperPeer.cpp @@ -68,7 +68,8 @@ bool WhisperPeer::interpret(unsigned _id, RLP const& _r) { unsigned n = 0; for (auto i: _r) - host()->inject(Envelope(i), this); + if (n++) + host()->inject(Envelope(i), this); break; } default: From ca7df0afa3b3a4869bfec1839dbf947ee241fe46 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 15 May 2015 13:25:44 +0200 Subject: [PATCH 088/157] Store copied assembly items in test. Fixes OSX issues. --- test/libsolidity/SolidityOptimizer.cpp | 29 ++++++++++++-------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index e8cc2d5b5..744fc48ae 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -97,7 +97,7 @@ public: { eth::KnownState state; for (auto const& item: addDummyLocations(_input)) - state.feedItem(item); + state.feedItem(item, true); return state; } @@ -884,21 +884,18 @@ 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))); } -// ****************************** -// DISABLED DUE TO FAILURE ON OSX -// ****************************** -//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_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) { From 177e99c29b62e7765b7c3dacaa7d556b8af4aa04 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 15 May 2015 15:12:34 +0200 Subject: [PATCH 089/157] bug fix --- mix/CodeModel.cpp | 5 +++-- mix/CodeModel.h | 2 +- mix/qml/html/codeeditor.js | 20 ++++++++++++++++---- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 15d5a7679..7a0325b7a 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -352,7 +352,7 @@ void CodeModel::gasEstimation(solidity::CompilerStack const& _cs) for (auto gasIte = gasCosts.begin(); gasIte != gasCosts.end(); ++gasIte) { - SourceLocation location = gasIte->first->getLocation(); + SourceLocation const& location = gasIte->first->getLocation(); GasMeter::GasConsumption cost = gasIte->second; std::stringstream v; v << cost.value; @@ -364,7 +364,8 @@ void CodeModel::gasEstimation(solidity::CompilerStack const& _cs) QVariantList CodeModel::gasCostByDocumentId(QString const& _documentId) const { - if (m_gasCostsMaps.contains(_documentId)) + auto ite = m_gasCostsMaps.find(_documentId); + if (ite != m_gasCostsMaps.end()) { auto sourceMapIter = m_gasCostsMaps.find(_documentId); return sourceMapIter.value(); diff --git a/mix/CodeModel.h b/mix/CodeModel.h index f5a170da6..7cc9d3477 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -137,7 +137,7 @@ class GasMap: public QObject Q_PROPERTY(bool isInfinite MEMBER m_isInfinite CONSTANT) public: - GasMap(int _start, int _end, QString _gas, bool _isInfinite): m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite) {} + GasMap(int _start, int _end, QString _gas, bool _isInfinite): m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } int m_start; int m_end; diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index 7d68f4032..d1ecf0380 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -215,7 +215,6 @@ var gasCosts = null; setGasCosts = function(_gasCosts) { gasCosts = JSON.parse(_gasCosts); - if (showingGasEstimation) { displayGasEstimation(false); @@ -278,12 +277,13 @@ var gasAnnotation; function listenMouseOver(e) { var node = e.target || e.srcElement; - if (node) { - if (!gasAnnotation && node.className && node.className.indexOf("CodeMirror-gasCosts") !== -1) + if (node) + { + if (node.className && node.className.indexOf("CodeMirror-gasCosts") !== -1) { if (gasAnnotation) gasAnnotation.clear(); - var cl = node.className.split(" ")[1]; + var cl = getClass(node); var gasTitle = gasMarkRef[cl].value.isInfinite ? "infinite" : gasMarkRef[cl].value.gas; gasTitle = gasTitle + " gas"; gasAnnotation = editor.addLineWidget(gasMarkRef[cl].line + 1, makeGasCostMarker(gasTitle), { coverGutter: false, above: true }); @@ -296,7 +296,19 @@ function listenMouseOver(e) } } +function getClass(node) +{ + var classes = node.className.split(" "); + for (var k in classes) + { + if (classes[k].indexOf("CodeMirror-gasCosts") !== -1) + return classes[k]; + } + return ""; +} + // blue => red ["#1515ED", "#1714EA", "#1914E8", "#1B14E6", "#1D14E4", "#1F14E2", "#2214E0", "#2414DE", "#2614DC", "#2813DA", "#2A13D8", "#2D13D6", "#2F13D4", "#3113D2", "#3313D0", "#3513CE", "#3713CC", "#3A12CA", "#3C12C8", "#3E12C6", "#4012C4", "#4212C2", "#4512C0", "#4712BE", "#4912BC", "#4B11BA", "#4D11B8", "#4F11B6", "#5211B4", "#5411B2", "#5611B0", "#5811AE", "#5A11AC", "#5D11AA", "#5F10A7", "#6110A5", "#6310A3", "#6510A1", "#67109F", "#6A109D", "#6C109B", "#6E1099", "#700F97", "#720F95", "#750F93", "#770F91", "#790F8F", "#7B0F8D", "#7D0F8B", "#7F0F89", "#820E87", "#840E85", "#860E83", "#880E81", "#8A0E7F", "#8D0E7D", "#8F0E7B", "#910E79", "#930D77", "#950D75", "#970D73", "#9A0D71", "#9C0D6F", "#9E0D6D", "#A00D6B", "#A20D69", "#A50D67", "#A70C64", "#A90C62", "#AB0C60", "#AD0C5E", "#AF0C5C", "#B20C5A", "#B40C58", "#B60C56", "#B80B54", "#BA0B52", "#BD0B50", "#BF0B4E", "#C10B4C", "#C30B4A", "#C50B48", "#C70B46", "#CA0A44", "#CC0A42", "#CE0A40", "#D00A3E", "#D20A3C", "#D50A3A", "#D70A38", "#D90A36", "#DB0934", "#DD0932", "#DF0930", "#E2092E", "#E4092C", "#E6092A", "#E80928", "#EA0926", "#ED0924"] /* green => red */ var colorGradient = ["#429C27", "#439A26", "#449926", "#469726", "#479626", "#489525", "#4A9325", "#4B9225", "#4D9025", "#4E8F25", "#4F8E24", "#518C24", "#528B24", "#548924", "#558824", "#568723", "#588523", "#598423", "#5B8223", "#5C8122", "#5D8022", "#5F7E22", "#607D22", "#627B22", "#637A21", "#647921", "#667721", "#677621", "#697421", "#6A7320", "#6B7220", "#6D7020", "#6E6F20", "#706E20", "#716C1F", "#726B1F", "#74691F", "#75681F", "#76671E", "#78651E", "#79641E", "#7B621E", "#7C611E", "#7D601D", "#7F5E1D", "#805D1D", "#825B1D", "#835A1D", "#84591C", "#86571C", "#87561C", "#89541C", "#8A531B", "#8B521B", "#8D501B", "#8E4F1B", "#904D1B", "#914C1A", "#924B1A", "#94491A", "#95481A", "#97461A", "#984519", "#994419", "#9B4219", "#9C4119", "#9E4019", "#9F3E18", "#A03D18", "#A23B18", "#A33A18", "#A43917", "#A63717", "#A73617", "#A93417", "#AA3317", "#AB3216", "#AD3016", "#AE2F16", "#B02D16", "#B12C16", "#B22B15", "#B42915", "#B52815", "#B72615", "#B82514", "#B92414", "#BB2214", "#BC2114", "#BE1F14", "#BF1E13", "#C01D13", "#C21B13", "#C31A13", "#C51813", "#C61712", "#C71612", "#C91412", "#CA1312", "#CC1212"] + editor.setOption("extraKeys", extraKeys); From eca68b12587f9f6c2b2203c191b929b05b289ba9 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 15 May 2015 15:14:23 +0200 Subject: [PATCH 090/157] small change --- mix/qml/html/codeeditor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index d1ecf0380..6499922ae 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -283,7 +283,7 @@ function listenMouseOver(e) { if (gasAnnotation) gasAnnotation.clear(); - var cl = getClass(node); + var cl = getGasCostClass(node); var gasTitle = gasMarkRef[cl].value.isInfinite ? "infinite" : gasMarkRef[cl].value.gas; gasTitle = gasTitle + " gas"; gasAnnotation = editor.addLineWidget(gasMarkRef[cl].line + 1, makeGasCostMarker(gasTitle), { coverGutter: false, above: true }); @@ -296,7 +296,7 @@ function listenMouseOver(e) } } -function getClass(node) +function getGasCostClass(node) { var classes = node.className.split(" "); for (var k in classes) From b4912db1c6263e53e0fdc5614740f03ba5e2a099 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 15 May 2015 15:27:31 +0200 Subject: [PATCH 091/157] Succint interfaces. --- libsolidity/InterfaceHandler.cpp | 6 +++--- libsolidity/InterfaceHandler.h | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/libsolidity/InterfaceHandler.cpp b/libsolidity/InterfaceHandler.cpp index a49c4dc3f..85026ac12 100644 --- a/libsolidity/InterfaceHandler.cpp +++ b/libsolidity/InterfaceHandler.cpp @@ -101,7 +101,7 @@ std::unique_ptr InterfaceHandler::getABIInterface(ContractDefinitio event["inputs"] = params; abi.append(event); } - return std::unique_ptr(new std::string(m_writer.write(abi))); + return std::unique_ptr(new std::string(Json::FastWriter().write(abi))); } unique_ptr InterfaceHandler::getABISolidityInterface(ContractDefinition const& _contractDef) @@ -153,7 +153,7 @@ std::unique_ptr InterfaceHandler::getUserDocumentation(ContractDefi } doc["methods"] = methods; - return std::unique_ptr(new std::string(m_writer.write(doc))); + return std::unique_ptr(new std::string(Json::FastWriter().write(doc))); } std::unique_ptr InterfaceHandler::getDevDocumentation(ContractDefinition const& _contractDef) @@ -217,7 +217,7 @@ std::unique_ptr InterfaceHandler::getDevDocumentation(ContractDefin } doc["methods"] = methods; - return std::unique_ptr(new std::string(m_writer.write(doc))); + return std::unique_ptr(new std::string(Json::FastWriter().write(doc))); } /* -- private -- */ diff --git a/libsolidity/InterfaceHandler.h b/libsolidity/InterfaceHandler.h index 6aa3f72d6..405181890 100644 --- a/libsolidity/InterfaceHandler.h +++ b/libsolidity/InterfaceHandler.h @@ -108,8 +108,6 @@ private: std::string const& _tag, CommentOwner _owner); - Json::StyledWriter m_writer; - // internal state DocTagType m_lastTag; std::string m_notice; From eeceeea3d440fd07a0c5a7f1fc4b1124ef9401df Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 15 May 2015 15:36:14 +0200 Subject: [PATCH 092/157] Hex/decimal cleanup for assembly output. --- libevmasm/Assembly.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 1011392b9..6f38b0f42 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -121,13 +121,13 @@ ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap con _out << " " << instructionInfo(i.instruction()).name << "\t" << i.getJumpTypeAsString(); break; case Push: - _out << " PUSH " << i.data(); + _out << " PUSH " << hex << i.data(); break; case PushString: _out << " PUSH \"" << m_strings.at((h256)i.data()) << "\""; break; case PushTag: - _out << " PUSH [tag" << i.data() << "]"; + _out << " PUSH [tag" << dec << i.data() << "]"; break; case PushSub: _out << " PUSH [$" << h256(i.data()).abridged() << "]"; @@ -139,7 +139,7 @@ ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap con _out << " PUSHSIZE"; break; case Tag: - _out << "tag" << i.data() << ": " << endl << _prefix << " JUMPDEST"; + _out << "tag" << dec << i.data() << ": " << endl << _prefix << " JUMPDEST"; break; case PushData: _out << " PUSH [" << hex << (unsigned)i.data() << "]"; @@ -208,7 +208,7 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes break; case PushTag: collection.append( - createJsonValue("PUSH [tag]", i.getLocation().start, i.getLocation().end, toStringInHex(i.data()))); + createJsonValue("PUSH [tag]", i.getLocation().start, i.getLocation().end, string(i.data()))); break; case PushSub: collection.append( @@ -223,19 +223,13 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes createJsonValue("PUSHSIZE", i.getLocation().start, i.getLocation().end)); break; case Tag: - { collection.append( createJsonValue("tag", i.getLocation().start, i.getLocation().end, string(i.data()))); collection.append( createJsonValue("JUMDEST", i.getLocation().start, i.getLocation().end)); - } break; case PushData: - { - Json::Value pushData; - pushData["name"] = "PUSH hex"; - collection.append(createJsonValue("PUSH hex", i.getLocation().start, i.getLocation().end, toStringInHex(i.data()))); - } + collection.append(createJsonValue("PUSH data", i.getLocation().start, i.getLocation().end, toStringInHex(i.data()))); break; default: BOOST_THROW_EXCEPTION(InvalidOpcode()); From 51ddf29763bb61cdd60d96589129647bfbe27290 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 15 May 2015 15:42:23 +0200 Subject: [PATCH 093/157] small changes --- mix/CodeModel.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 7a0325b7a..137188e40 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -350,13 +350,13 @@ void CodeModel::gasEstimation(solidity::CompilerStack const& _cs) StructuralGasEstimator estimator; std::map gasCosts = estimator.breakToStatementLevel(estimator.performEstimation(*items, std::vector({&sourceUnit})), {&sourceUnit}); - for (auto gasIte = gasCosts.begin(); gasIte != gasCosts.end(); ++gasIte) + for (auto gasItem = gasCosts.begin(); gasItem != gasCosts.end(); ++gasItem) { - SourceLocation const& location = gasIte->first->getLocation(); - GasMeter::GasConsumption cost = gasIte->second; + SourceLocation const& location = gasItem->first->getLocation(); + GasMeter::GasConsumption cost = gasItem->second; std::stringstream v; v << cost.value; - GasMap* gas = new GasMap(location.start, location.end, QString::fromStdString(v.str()), gasIte->second.isInfinite); + GasMap* gas = new GasMap(location.start, location.end, QString::fromStdString(v.str()), cost.isInfinite); m_gasCostsMaps.find(sourceName).value().push_back(QVariant::fromValue(gas)); } } @@ -364,12 +364,9 @@ void CodeModel::gasEstimation(solidity::CompilerStack const& _cs) QVariantList CodeModel::gasCostByDocumentId(QString const& _documentId) const { - auto ite = m_gasCostsMaps.find(_documentId); - if (ite != m_gasCostsMaps.end()) - { - auto sourceMapIter = m_gasCostsMaps.find(_documentId); - return sourceMapIter.value(); - } + auto gasIter = m_gasCostsMaps.find(_documentId); + if (gasIter != m_gasCostsMaps.end()) + return gasIter.value(); else return QVariantList(); } From 65bcb451d4e186274d566e391d4a91da097bd315 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 15 May 2015 17:00:08 +0200 Subject: [PATCH 094/157] Function hashes for JSON compiler. --- solc/jsonCompiler.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/solc/jsonCompiler.cpp b/solc/jsonCompiler.cpp index 6f3834af4..d47903fca 100644 --- a/solc/jsonCompiler.cpp +++ b/solc/jsonCompiler.cpp @@ -50,6 +50,14 @@ string formatError(Exception const& _exception, string const& _name, CompilerSta return Json::FastWriter().write(output); } +Json::Value functionHashes(ContractDefinition const& _contract) +{ + Json::Value functionHashes(Json::objectValue); + for (auto const& it: _contract.getInterfaceFunctions()) + functionHashes[it.second->externalSignature()] = toHex(it.first.ref()); + return functionHashes; +} + string compile(string _input, bool _optimize) { StringMap sources; @@ -100,6 +108,7 @@ string compile(string _input, bool _optimize) contractData["interface"] = compiler.getInterface(contractName); contractData["bytecode"] = toHex(compiler.getBytecode(contractName)); contractData["opcodes"] = eth::disassemble(compiler.getBytecode(contractName)); + contractData["functionHashes"] = functionHashes(compiler.getContractDefinition(contractName)); ostringstream unused; contractData["assembly"] = compiler.streamAssembly(unused, contractName, sources, true); output["contracts"][contractName] = contractData; From 74c2179c55afd7a5a9ac0993fa2dbe122e02abb7 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 15 May 2015 17:28:34 +0200 Subject: [PATCH 095/157] Don't echo written password under win32 --- libdevcore/CommonIO.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/libdevcore/CommonIO.cpp b/libdevcore/CommonIO.cpp index d37f74db2..9538ca55f 100644 --- a/libdevcore/CommonIO.cpp +++ b/libdevcore/CommonIO.cpp @@ -24,7 +24,10 @@ #include #include #include "Exceptions.h" -#ifndef _WIN32 +#include +#ifdef _WIN32 +#include +#else #include #endif using namespace std; @@ -125,8 +128,22 @@ std::string dev::getPassword(std::string const& _prompt) { #if WIN32 cout << _prompt << flush; + // Get current Console input flags + HANDLE hStdin; + DWORD fdwSaveOldMode; + if ((hStdin = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) + BOOST_THROW_EXCEPTION(ExternalFunctionFailure("GetStdHandle")); + if (!GetConsoleMode(hStdin, &fdwSaveOldMode)) + BOOST_THROW_EXCEPTION(ExternalFunctionFailure("GetConsoleMode")); + // Set console flags to no echo + if (!SetConsoleMode(hStdin, fdwSaveOldMode & (~ENABLE_ECHO_INPUT))) + BOOST_THROW_EXCEPTION(ExternalFunctionFailure("SetConsoleMode")); + // Read the string std::string ret; std::getline(cin, ret); + // Restore old input mode + if (!SetConsoleMode(hStdin, fdwSaveOldMode)) + BOOST_THROW_EXCEPTION(ExternalFunctionFailure("SetConsoleMode")); return ret; #else struct termios oflags; From 01aced01890f0e5ba29c0ebe6d9f3069cd2a173f Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 15 May 2015 17:36:20 +0200 Subject: [PATCH 096/157] fixed gas calculation --- mix/MixClient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index cac208ba4..e3ed2eead 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -220,7 +220,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c d.address = _t.receiveAddress(); d.sender = _t.sender(); d.value = _t.value(); - d.gasUsed = er.gasUsed + er.gasRefunded; + d.gasUsed = er.gasUsed + er.gasRefunded + c_callStipend; if (_t.isCreation()) d.contractAddress = right160(sha3(rlpList(_t.sender(), _t.nonce()))); if (!_call) @@ -234,7 +234,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c 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")); - d.gasUsed = er.gasUsed + er.gasRefunded + er.gasForDeposit; + d.gasUsed = er.gasUsed + er.gasRefunded + er.gasForDeposit + c_callStipend; // collect watches h256Set changed; Guard l(x_filtersWatches); From 135513f18a1851bc18a2d4f01ecf76d376abc2e9 Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 15 May 2015 17:56:44 +0200 Subject: [PATCH 097/157] globalreg address --- mix/qml/DeploymentDialog.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mix/qml/DeploymentDialog.qml b/mix/qml/DeploymentDialog.qml index 1fbde3ac9..81092ec76 100644 --- a/mix/qml/DeploymentDialog.qml +++ b/mix/qml/DeploymentDialog.qml @@ -15,7 +15,7 @@ Dialog { id: modalDeploymentDialog modality: Qt.ApplicationModal width: 735 - height: 400 + height: 450 visible: false property int ownedRegistrarDeployGas: 1179075 // TODO: Use sol library to calculate gas requirement for each tr. property int ownedRegistrarSetSubRegistrarGas: 50000 @@ -293,15 +293,15 @@ Dialog { DefaultLabel { text: qsTr("Root Registrar address:") - visible: false //still use it for now in dev env. + visible: true //still use it for now in dev env. } DefaultTextField { Layout.preferredWidth: 350 id: registrarAddr - text: "ab69f864e49fc4294d18355c4bafb0b91b5e629b" - visible: false + text: "c6d9d2cd449a754c494264e1809c50e34d64562b" + visible: true } DefaultLabel From 47b6e38df9d56866af2093516c364e1921acd506 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 15 May 2015 17:58:31 +0200 Subject: [PATCH 098/157] Fixes for transact gas usage. --- alethzero/Transact.cpp | 2 +- libethcore/Ethash.cpp | 2 +- libethcore/EthashAux.cpp | 6 ++++-- libethcore/EthashAux.h | 7 +++++-- libethereum/Executive.h | 2 +- libethereum/TransactionQueue.cpp | 11 ++++++++--- mix/qml/DeploymentDialog.qml | 4 ++-- 7 files changed, 22 insertions(+), 12 deletions(-) diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index f2a8ef0d5..1336c3f05 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -361,7 +361,7 @@ void Transact::rejigData() to = m_context->fromString(ui->destination->currentText().toStdString()).first; er = ethereum()->call(s, value(), to, m_data, gasNeeded, gasPrice()); } - gasNeeded = (qint64)(er.gasUsed + er.gasRefunded); + gasNeeded = (qint64)(er.gasUsed + er.gasRefunded + c_callStipend); htmlInfo = QString("
INFO Gas required: %1 total = %2 base, %3 exec [%4 refunded later]
").arg(gasNeeded).arg(baseGas).arg(gasNeeded - baseGas).arg((qint64)er.gasRefunded) + htmlInfo; if (er.excepted != TransactionException::None) diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 80550886c..fedf23826 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -317,7 +317,7 @@ void Ethash::GPUMiner::workLoop() } if (shouldStop()) return; - EthashAux::FullType dag = EthashAux::full(EthashAux::number(w.seedHash)); + EthashAux::FullType dag = EthashAux::full(EthashAux::number(w.seedHash)); // todo , , false bytesConstRef dagData = dag->data(); m_miner->init(dagData.data(), dagData.size(), 32, s_platformId, device); } diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index 9287bcbfc..2f369c458 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -156,8 +156,10 @@ static int dagCallbackShim(unsigned _p) return s_dagCallback ? s_dagCallback(_p) : 0; } -EthashAux::FullType EthashAux::full(uint64_t _blockNumber, function const& _f) +EthashAux::FullType EthashAux::full(uint64_t _blockNumber, function const& _f, bool _createIfMissing) { + (void)_createIfMissing; + // TODO: implement auto l = light(_blockNumber); h256 seedHash = EthashAux::seedHash(_blockNumber); FullType ret; @@ -195,7 +197,7 @@ unsigned EthashAux::computeFull(uint64_t _blockNumber) get()->m_generatingFullNumber = _blockNumber / ETHASH_EPOCH_LENGTH * ETHASH_EPOCH_LENGTH; get()->m_fullGenerator = unique_ptr(new thread([=](){ cnote << "Loading full DAG of" << _blockNumber; - get()->full(_blockNumber, [](unsigned p){ get()->m_fullProgress = p; return 0; }); + get()->full(_blockNumber, [](unsigned p){ get()->m_fullProgress = p; return 0; }), true; cnote << "Full DAG loaded"; get()->m_fullProgress = 0; get()->m_generatingFullNumber = NotGenerating; diff --git a/libethcore/EthashAux.h b/libethcore/EthashAux.h index f57f7a4d3..bc87f9dff 100644 --- a/libethcore/EthashAux.h +++ b/libethcore/EthashAux.h @@ -73,8 +73,9 @@ public: static unsigned computeFull(uint64_t _blockNumber); /// Information on the generation progress. static std::pair fullGeneratingProgress() { return std::make_pair(get()->m_generatingFullNumber, get()->m_fullProgress); } - /// Kicks off generation of DAG for @a _blocknumber and blocks until ready; @returns result. - static FullType full(uint64_t _blockNumber, std::function const& _f = std::function()); + + /// Kicks off generation of DAG for @a _blocknumber and blocks until ready; @returns result or empty pointer if not existing. + static FullType full(uint64_t _blockNumber, std::function const& _f = std::function(), bool _createIfMissing = false); static Ethash::Result eval(BlockInfo const& _header) { return eval(_header, _header.nonce); } static Ethash::Result eval(BlockInfo const& _header, Nonce const& _nonce); @@ -83,6 +84,8 @@ public: private: EthashAux() {} + /// Kicks off generation of DAG for @a _blocknumber and blocks until ready; @returns result. + void killCache(h256 const& _s); static EthashAux* s_this; diff --git a/libethereum/Executive.h b/libethereum/Executive.h index 8903fd464..3806221be 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -137,7 +137,7 @@ private: Transaction m_t; ///< The original transaction. Set by setup(). LogEntries m_logs; ///< The log entries created by this transaction. Set by finalize(). - bigint m_gasRequired; + bigint m_gasRequired; ///< Gas required during execution of the transaction. bigint m_gasCost; bigint m_totalCost; }; diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 5aca67a29..11104705c 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -41,9 +41,14 @@ ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallb if (ir != ImportResult::Success) return ir; - Transaction t(_transactionRLP, CheckTransaction::Everything); - UpgradeGuard ul(l); - return manageImport_WITH_LOCK(h, t, _cb); + try { + Transaction t(_transactionRLP, CheckTransaction::Everything); + UpgradeGuard ul(l); + return manageImport_WITH_LOCK(h, t, _cb); + } + catch (...) { + return ImportResult::Malformed; + } } ImportResult TransactionQueue::check_WITH_LOCK(h256 const& _h, IfDropped _ik) diff --git a/mix/qml/DeploymentDialog.qml b/mix/qml/DeploymentDialog.qml index 1fbde3ac9..e2d15d487 100644 --- a/mix/qml/DeploymentDialog.qml +++ b/mix/qml/DeploymentDialog.qml @@ -300,8 +300,8 @@ Dialog { { Layout.preferredWidth: 350 id: registrarAddr - text: "ab69f864e49fc4294d18355c4bafb0b91b5e629b" - visible: false + text: "c6d9d2cd449a754c494264e1809c50e34d64562b" + } DefaultLabel From 4c69ecf16bc5f0a978d10d215a1aa76a52d8db38 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 15 May 2015 18:02:09 +0200 Subject: [PATCH 099/157] Bare callcode for addresses and contracts. --- libsolidity/ExpressionCompiler.cpp | 37 ++++++++++++++--------- libsolidity/ExpressionCompiler.h | 6 ++-- libsolidity/Types.cpp | 23 ++++++++++++-- libsolidity/Types.h | 37 +++++++++++++++++------ test/libsolidity/SolidityEndToEndTest.cpp | 31 +++++++++++++++++++ 5 files changed, 106 insertions(+), 28 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 76d05bd0a..838ee264e 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -458,9 +458,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) break; } case Location::External: + case Location::CallCode: case Location::Bare: + case Location::BareCallCode: _functionCall.getExpression().accept(*this); - appendExternalFunctionCall(function, arguments, function.getLocation() == Location::Bare); + appendExternalFunctionCall(function, arguments); break; case Location::Creation: { @@ -527,13 +529,12 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) TypePointers{}, strings(), strings(), - Location::External, + Location::Bare, false, true, true ), - {}, - true + {} ); break; case Location::Suicide: @@ -622,7 +623,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) m_context << contractAddresses.find(function.getLocation())->second; for (unsigned i = function.getSizeOnStack(); i > 0; --i) m_context << eth::swapInstruction(i); - appendExternalFunctionCall(function, arguments, true); + appendExternalFunctionCall(function, arguments); break; } default: @@ -685,7 +686,7 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) IntegerType(0, IntegerType::Modifier::Address), true); m_context << eth::Instruction::BALANCE; } - else if (member == "send" || member.substr(0, min(member.size(), 4)) == "call") + else if ((set{"send", "call", "callcode"}).count(member)) appendTypeConversion(*_memberAccess.getExpression().getType(), IntegerType(0, IntegerType::Modifier::Address), true); else @@ -1031,9 +1032,10 @@ void ExpressionCompiler::appendHighBitsCleanup(IntegerType const& _typeOnStack) m_context << ((u256(1) << _typeOnStack.getNumBits()) - 1) << eth::Instruction::AND; } -void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functionType, - vector> const& _arguments, - bool bare) +void ExpressionCompiler::appendExternalFunctionCall( + FunctionType const& _functionType, + vector> const& _arguments +) { solAssert(_functionType.takesArbitraryParameters() || _arguments.size() == _functionType.getParameterTypes().size(), ""); @@ -1047,7 +1049,7 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio unsigned gasValueSize = (_functionType.gasSet() ? 1 : 0) + (_functionType.valueSet() ? 1 : 0); - unsigned contractStackPos = m_context.currentToBaseStackOffset(1 + gasValueSize + (bare ? 0 : 1)); + unsigned contractStackPos = m_context.currentToBaseStackOffset(1 + gasValueSize + (_functionType.isBareCall() ? 0 : 1)); unsigned gasStackPos = m_context.currentToBaseStackOffset(gasValueSize); unsigned valueStackPos = m_context.currentToBaseStackOffset(1); @@ -1057,7 +1059,7 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio unsigned retSize = firstType ? firstType->getCalldataEncodedSize() : 0; m_context << u256(retSize) << u256(0); - if (bare) + if (_functionType.isBareCall()) m_context << u256(0); else { @@ -1074,7 +1076,8 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio _arguments, _functionType.getParameterTypes(), _functionType.padArguments(), - bare, + _functionType.getLocation() == FunctionType::Location::Bare || + _functionType.getLocation() == FunctionType::Location::BareCallCode, _functionType.takesArbitraryParameters() ); @@ -1093,14 +1096,20 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio // send all gas except the amount needed to execute "SUB" and "CALL" // @todo this retains too much gas for now, needs to be fine-tuned. m_context << u256(50 + (_functionType.valueSet() ? 9000 : 0) + 25000) << eth::Instruction::GAS << eth::Instruction::SUB; - m_context << eth::Instruction::CALL; + if ( + _functionType.getLocation() == FunctionType::Location::CallCode || + _functionType.getLocation() == FunctionType::Location::BareCallCode + ) + m_context << eth::Instruction::CALLCODE; + else + m_context << eth::Instruction::CALL; auto tag = m_context.appendConditionalJump(); m_context << eth::Instruction::STOP << tag; // STOP if CALL leaves 0. if (_functionType.valueSet()) m_context << eth::Instruction::POP; if (_functionType.gasSet()) m_context << eth::Instruction::POP; - if (!bare) + if (!_functionType.isBareCall()) m_context << eth::Instruction::POP; m_context << eth::Instruction::POP; // pop contract address diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index 45a2311ef..954e32c84 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/ExpressionCompiler.h @@ -98,8 +98,10 @@ private: void appendHighBitsCleanup(IntegerType const& _typeOnStack); /// Appends code to call a function of the given type with the given arguments. - void appendExternalFunctionCall(FunctionType const& _functionType, std::vector> const& _arguments, - bool bare = false); + void appendExternalFunctionCall( + FunctionType const& _functionType, + std::vector> const& _arguments + ); /// Appends code that evaluates the given arguments and moves the result to memory encoded as /// specified by the ABI. The memory offset is expected to be on the stack and is updated by /// this call. If @a _padToWordBoundaries is set to false, all values are concatenated without diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 7a5b309d9..d1f51decf 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -316,6 +316,7 @@ TypePointer IntegerType::binaryOperatorResult(Token::Value _operator, TypePointe const MemberList IntegerType::AddressMemberList({ {"balance", make_shared(256)}, {"call", make_shared(strings(), strings(), FunctionType::Location::Bare, true)}, + {"callcode", make_shared(strings(), strings(), FunctionType::Location::BareCallCode, true)}, {"send", make_shared(strings{"uint"}, strings{}, FunctionType::Location::Send)} }); @@ -1115,9 +1116,11 @@ unsigned FunctionType::getSizeOnStack() const } unsigned size = 0; - if (location == Location::External) + if (location == Location::External || location == Location::CallCode) size = 2; - else if (location == Location::Internal || location == Location::Bare) + else if (location == Location::Bare || location == Location::BareCallCode) + size = 1; + else if (location == Location::Internal) size = 1; if (m_gasSet) size++; @@ -1156,6 +1159,7 @@ MemberList const& FunctionType::getMembers() const case Location::SHA256: case Location::RIPEMD160: case Location::Bare: + case Location::BareCallCode: if (!m_members) { MemberList::MemberMap members{ @@ -1228,6 +1232,21 @@ bool FunctionType::hasEqualArgumentTypes(FunctionType const& _other) const ); } +bool FunctionType::isBareCall() const +{ + switch (m_location) + { + case Location::Bare: + case Location::BareCallCode: + case Location::ECRecover: + case Location::SHA256: + case Location::RIPEMD160: + return true; + default: + return false; + } +} + string FunctionType::externalSignature(std::string const& _name) const { std::string funcName = _name; diff --git a/libsolidity/Types.h b/libsolidity/Types.h index da2fcdb89..a69df964c 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -540,17 +540,32 @@ private: class FunctionType: public Type { public: - /// The meaning of the value(s) on the stack referencing the function: - /// INTERNAL: jump tag, EXTERNAL: contract address + function identifier, - /// BARE: contract address (non-abi contract call) - /// OTHERS: special virtual function, nothing on the stack + /// How this function is invoked on the EVM. /// @todo This documentation is outdated, and Location should rather be named "Type" - enum class Location { Internal, External, Creation, Send, - SHA3, Suicide, - ECRecover, SHA256, RIPEMD160, - Log0, Log1, Log2, Log3, Log4, Event, - SetGas, SetValue, BlockHash, - Bare }; + enum class Location + { + Internal, ///< stack-call using plain JUMP + External, ///< external call using CALL + CallCode, ///< extercnal call using CALLCODE, i.e. not exchanging the storage + Bare, ///< CALL without function hash + BareCallCode, ///< CALLCODE without function hash + Creation, ///< external call using CREATE + Send, ///< CALL, but without data and gas + SHA3, ///< SHA3 + Suicide, ///< SUICIDE + ECRecover, ///< CALL to special contract for ecrecover + SHA256, ///< CALL to special contract for sha256 + RIPEMD160, ///< CALL to special contract for ripemd160 + Log0, + Log1, + Log2, + Log3, + Log4, + Event, ///< syntactic sugar for LOG* + SetGas, ///< modify the default gas value for the function call + SetValue, ///< modify the default value transfer for the function call + BlockHash ///< BLOCKHASH + }; virtual Category getCategory() const override { return Category::Function; } @@ -620,6 +635,8 @@ public: /// @returns true if the types of parameters are equal (does't check return parameter types) bool hasEqualArgumentTypes(FunctionType const& _other) const; + /// @returns true if the ABI is used for this call (only meaningful for external calls) + bool isBareCall() const; Location const& getLocation() const { return m_location; } /// @returns the external signature of this function type given the function name /// If @a _name is not provided (empty string) then the @c m_declaration member of the diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index ed5f1acdf..6713382fa 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -2558,6 +2558,37 @@ BOOST_AUTO_TEST_CASE(generic_call) BOOST_CHECK_EQUAL(m_state.balance(m_contractAddress), 50 - 2); } +BOOST_AUTO_TEST_CASE(generic_callcode) +{ + char const* sourceCode = R"**( + contract receiver { + uint public received; + function receive(uint256 x) { received = x; } + } + contract sender { + uint public received; + function doSend(address rec) returns (uint d) + { + bytes4 signature = bytes4(bytes32(sha3("receive(uint256)"))); + rec.callcode.value(2)(signature, 23); + return receiver(rec).received(); + } + } + )**"; + compileAndRun(sourceCode, 0, "receiver"); + u160 const c_receiverAddress = m_contractAddress; + compileAndRun(sourceCode, 50, "sender"); + u160 const c_senderAddress = m_contractAddress; + BOOST_CHECK(callContractFunction("doSend(address)", c_receiverAddress) == encodeArgs(0)); + BOOST_CHECK(callContractFunction("received()") == encodeArgs(23)); + m_contractAddress = c_receiverAddress; + BOOST_CHECK(callContractFunction("received()") == encodeArgs(0)); + BOOST_CHECK(m_state.storage(c_receiverAddress).empty()); + BOOST_CHECK(!m_state.storage(c_senderAddress).empty()); + BOOST_CHECK_EQUAL(m_state.balance(c_receiverAddress), 0); + BOOST_CHECK_EQUAL(m_state.balance(c_senderAddress), 50); +} + BOOST_AUTO_TEST_CASE(store_bytes) { // this test just checks that the copy loop does not mess up the stack From 3145b5aa7d6bdcaf2aa14d2ed6e627af95e5458b Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 15 May 2015 09:48:58 +0200 Subject: [PATCH 100/157] Throw if ethash_XXX_new() fails --- libethcore/EthashAux.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index 9bb2c4aa9..59155610f 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -116,6 +116,8 @@ EthashAux::LightAllocation::LightAllocation(h256 const& _seedHash) { uint64_t blockNumber = EthashAux::number(_seedHash); light = ethash_light_new(blockNumber); + if (!light) + BOOST_THROW_EXCEPTION(ExternalFunctionFailure("ethash_light_new()")); size = ethash_get_cachesize(blockNumber); } @@ -132,6 +134,8 @@ bytesConstRef EthashAux::LightAllocation::data() const EthashAux::FullAllocation::FullAllocation(ethash_light_t _light, ethash_callback_t _cb) { full = ethash_full_new(_light, _cb); + if (!full) + BOOST_THROW_EXCEPTION(ExternalFunctionFailure("ethash_full_new()")); } EthashAux::FullAllocation::~FullAllocation() From ed83256798a760486cf0003b11894b078f122891 Mon Sep 17 00:00:00 2001 From: Lars Pensjo Date: Sat, 16 May 2015 23:13:45 +0200 Subject: [PATCH 101/157] Enable -G without --opencl-device Otherwise, -G doesn't work. --- eth/main.cpp | 3 +++ ethminer/main.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/eth/main.cpp b/eth/main.cpp index 1eed535cd..26305f4da 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -787,11 +787,14 @@ int main(int argc, char** argv) else if (arg == "-C" || arg == "--cpu") minerType = MinerType::CPU; else if (arg == "-G" || arg == "--opencl") + { minerType = MinerType::GPU; + miningThreads = 1; /*<< " -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])); diff --git a/ethminer/main.cpp b/ethminer/main.cpp index 80895c975..c53fca481 100644 --- a/ethminer/main.cpp +++ b/ethminer/main.cpp @@ -398,7 +398,10 @@ int main(int argc, char** argv) else if (arg == "-C" || arg == "--cpu") minerType = MinerType::CPU; else if (arg == "-G" || arg == "--opencl") + { minerType = MinerType::GPU; + miningThreads = 1; + } else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc) { string m = boost::to_lower_copy(string(argv[++i])); From 462fa598435639777c6f099746d5b92956cf1d20 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 17 May 2015 13:00:48 +0200 Subject: [PATCH 102/157] Fix CPU mining. --- libethcore/Ethash.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 64ffa9549..ff7fe47e7 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -134,7 +134,10 @@ void Ethash::CPUMiner::workLoop() WorkPackage w = work(); - auto dag = EthashAux::full(w.seedHash); + EthashAux::FullType dag; + while (!shouldStop() && !(dag = EthashAux::full(w.seedHash))) + this_thread::sleep_for(chrono::milliseconds(500)); + h256 boundary = w.boundary; unsigned hashCount = 1; for (; !shouldStop(); tryNonce++, hashCount++) From 51cb83bd084deaab038e6f328ff2af56a3a0bd16 Mon Sep 17 00:00:00 2001 From: subtly Date: Sun, 17 May 2015 14:38:09 +0200 Subject: [PATCH 103/157] GetFolderPathW needs wchar_t and can otherwise fail (returning an invalid path) and use AppData path instead of users home directory. Use Local AppData instead of roaming to users on domain networks aren't uploading DAG files to servers. --- libethash/io_win32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libethash/io_win32.c b/libethash/io_win32.c index 2e6c8deb8..34f1aaa77 100644 --- a/libethash/io_win32.c +++ b/libethash/io_win32.c @@ -87,9 +87,9 @@ bool ethash_file_size(FILE* f, size_t* ret_size) bool ethash_get_default_dirname(char* strbuf, size_t buffsize) { - static const char dir_suffix[] = "Appdata\\Ethash\\"; + static const char dir_suffix[] = "Ethash\\"; strbuf[0] = '\0'; - if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, (WCHAR*)strbuf))) { + if (!SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, (CHAR*)strbuf))) { return false; } if (!ethash_strncat(strbuf, buffsize, "\\", 1)) { From e7a0b94786f1493fa1176bf47551eec832990cac Mon Sep 17 00:00:00 2001 From: subtly Date: Sun, 17 May 2015 19:00:58 +0200 Subject: [PATCH 104/157] Trigger dag creation prior to mining until threading on windows is sorted. Delete miner when returning early from gpu miner doWork so that in the event that abort is called prior to miner initializing, miner is still initialized. --- ethminer/main.cpp | 5 +++-- libethcore/Ethash.cpp | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ethminer/main.cpp b/ethminer/main.cpp index 97e125e65..bcb33915f 100644 --- a/ethminer/main.cpp +++ b/ethminer/main.cpp @@ -250,10 +250,11 @@ void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod) cnote << "Getting work package..."; Json::Value v = rpc.eth_getWork(); h256 hh(v[0].asString()); - if (hh != current.headerHash) + h256 newSeedHash(v[1].asString()); + if (hh != current.headerHash && !!EthashAux::full(newSeedHash, true)) { current.headerHash = hh; - current.seedHash = h256(v[1].asString()); + current.seedHash = newSeedHash; current.boundary = h256(fromHex(v[2].asString()), h256::AlignRight); cnote << "Got work package:"; cnote << " Header-hash:" << current.headerHash.hex(); diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index ff7fe47e7..72c340f70 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -319,7 +319,10 @@ void Ethash::GPUMiner::workLoop() if ((dag = EthashAux::full(w.seedHash, false))) break; if (shouldStop()) + { + delete m_miner; return; + } cnote << "Awaiting DAG"; this_thread::sleep_for(chrono::milliseconds(500)); } From ac60b992c6838d795bf1eaa0f77caf4ba12663d0 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 17 May 2015 19:21:33 +0200 Subject: [PATCH 105/157] Parallelised BlockQueue. Setup for using TrieRoot. --- alethzero/Main.ui | 12 ++ alethzero/MainWin.cpp | 9 +- alethzero/MainWin.h | 1 + alethzero/OurWebThreeStubServer.cpp | 3 + .../TrieHash.cpp | 33 +++- .../libdevcrypto => libdevcrypto}/TrieHash.h | 15 ++ libethcore/BlockInfo.cpp | 34 +++- libethereum/BlockChain.cpp | 129 ++++++++------- libethereum/BlockChain.h | 3 +- libethereum/BlockQueue.cpp | 156 +++++++++++++++--- libethereum/BlockQueue.h | 34 +++- libethereum/ClientBase.cpp | 2 +- libethereum/State.cpp | 38 +++-- libethereum/TransactionQueue.cpp | 125 +++++++++----- libethereum/TransactionQueue.h | 11 +- test/libdevcrypto/trie.cpp | 2 +- 16 files changed, 443 insertions(+), 164 deletions(-) rename {test/libdevcrypto => libdevcrypto}/TrieHash.cpp (89%) rename {test/libdevcrypto => libdevcrypto}/TrieHash.h (66%) diff --git a/alethzero/Main.ui b/alethzero/Main.ui index e0852142a..b5e22409d 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -185,6 +185,7 @@ + @@ -1733,6 +1734,17 @@ font-size: 14pt Prepare Next &DAG + + + true + + + true + + + Co&nfirm Transactions + + diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 9f630f37d..191db6eb4 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -212,7 +212,7 @@ Main::Main(QWidget *parent) : m_server->setIdentities(keysAsVector(owned())); m_server->StartListening(); - WebPage* webPage= new WebPage(this); + WebPage* webPage = new WebPage(this); m_webPage = webPage; connect(webPage, &WebPage::consoleMessage, [this](QString const& _msg) { Main::addConsoleMessage(_msg, QString()); }); ui->webView->setPage(m_webPage); @@ -368,6 +368,11 @@ Address Main::getCurrencies() const return abiOut
(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)3)).output); } +bool Main::doConfirm() +{ + return ui->confirm->isChecked(); +} + void Main::installNameRegWatch() { uninstallWatch(m_nameRegFilter); @@ -1151,7 +1156,7 @@ void Main::refreshBlockCount() { auto d = ethereum()->blockChain().details(); BlockQueueStatus b = ethereum()->blockQueueStatus(); - ui->chainStatus->setText(QString("%3 ready %4 future %5 unknown %6 bad %1 #%2").arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet").arg(d.number).arg(b.ready).arg(b.future).arg(b.unknown).arg(b.bad)); + ui->chainStatus->setText(QString("%3 ready %4 verifying %5 unverified %6 future %7 unknown %8 bad %1 #%2").arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet").arg(d.number).arg(b.verified).arg(b.verifying).arg(b.unverified).arg(b.future).arg(b.unknown).arg(b.bad)); } void Main::on_turboMining_triggered() diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index d9075d178..9f2082dd0 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -94,6 +94,7 @@ public: dev::u256 gasPrice() const { return 10 * dev::eth::szabo; } dev::eth::KeyManager& keyManager() override { return m_keyManager; } + bool doConfirm(); dev::Secret retrieveSecret(dev::Address const& _a) const override; diff --git a/alethzero/OurWebThreeStubServer.cpp b/alethzero/OurWebThreeStubServer.cpp index d3ee4f41b..7e9836818 100644 --- a/alethzero/OurWebThreeStubServer.cpp +++ b/alethzero/OurWebThreeStubServer.cpp @@ -146,6 +146,9 @@ AddressHash OurAccountHolder::realAccounts() const bool OurAccountHolder::validateTransaction(TransactionSkeleton const& _t, bool _toProxy) { + if (!m_main->doConfirm()) + return true; + if (_t.creation) { // show notice concerning the creation code. TODO: this needs entering into natspec. diff --git a/test/libdevcrypto/TrieHash.cpp b/libdevcrypto/TrieHash.cpp similarity index 89% rename from test/libdevcrypto/TrieHash.cpp rename to libdevcrypto/TrieHash.cpp index ccf12c162..0b02ce77f 100644 --- a/test/libdevcrypto/TrieHash.cpp +++ b/libdevcrypto/TrieHash.cpp @@ -20,8 +20,8 @@ */ #include "TrieHash.h" - #include +#include // @TODO replace ASAP! #include #include using namespace std; @@ -197,4 +197,35 @@ h256 hash256(u256Map const& _s) return sha3(s.out()); } +/*h256 orderedTrieRoot(std::vector const& _data) +{ + StringMap m; + unsigned j = 0; + for (auto i: _data) + m[asString(rlp(j++))] = asString(i); + return hash256(m); +}*/ + +h256 orderedTrieRoot(std::vector const& _data) +{ + MemoryDB db; + GenericTrieDB t(&db); + t.init(); + unsigned j = 0; + for (auto i: _data) + t.insert(rlp(j++), i.toBytes()); + return t.root(); +} + +h256 orderedTrieRoot(std::vector const& _data) +{ + MemoryDB db; + GenericTrieDB t(&db); + t.init(); + unsigned j = 0; + for (auto i: _data) + t.insert(rlp(j++), i); + return t.root(); +} + } diff --git a/test/libdevcrypto/TrieHash.h b/libdevcrypto/TrieHash.h similarity index 66% rename from test/libdevcrypto/TrieHash.h rename to libdevcrypto/TrieHash.h index be1d84480..b0588fc38 100644 --- a/test/libdevcrypto/TrieHash.h +++ b/libdevcrypto/TrieHash.h @@ -31,4 +31,19 @@ bytes rlp256(StringMap const& _s); h256 hash256(StringMap const& _s); h256 hash256(u256Map const& _s); +/*h256 orderedTrieRoot(std::vector const& _data); + +template inline h256 trieRootOver(unsigned _itemCount, T const& _getKey, U const& _getValue) +{ + StringMap m; + for (unsigned i = 0; i < _itemCount; ++i) + m[asString(_getKey(i))] = asString(_getValue(i)); + return hash256(m); +}*/ + +using bytesMap = std::unordered_map; + +h256 orderedTrieRoot(std::vector const& _data); +h256 orderedTrieRoot(std::vector const& _data); + } diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index e70b16753..00a5108c4 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include "EthashAux.h" @@ -173,6 +174,9 @@ void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s, h256 const void BlockInfo::populate(bytesConstRef _block, Strictness _s, h256 const& _h) { RLP root(_block); + if (!root.isList()) + BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("block needs to be a list") << BadFieldError(0, _block.toString())); + RLP header = root[0]; if (!header.isList()) @@ -185,6 +189,8 @@ void BlockInfo::populate(bytesConstRef _block, Strictness _s, h256 const& _h) BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("block uncles need to be a list") << BadFieldError(2, root[2].data().toString())); } +struct BlockInfoDiagnosticsChannel: public LogChannel { static const char* name() { return EthBlue "▧" EthWhite " ◌"; } static const int verbosity = 9; }; + template h256 trieRootOver(unsigned _itemCount, T const& _getKey, U const& _getValue) { MemoryDB db; @@ -195,17 +201,41 @@ 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); 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) + { + MemoryDB tm; + GenericTrieDB transactionsTrie(&tm); + transactionsTrie.init(); + + vector txs; + + for (unsigned i = 0; i < txList.itemCount(); ++i) + { + RLPStream k; + k << i; + + transactionsTrie.insert(&k.out(), txList[i].data()); + + txs.push_back(txList[i].data()); + cdebug << toHex(k.out()) << toHex(txList[i].data()); + } + cdebug << "trieRootOver" << expectedRoot; + cdebug << "orderedTrieRoot" << orderedTrieRoot(txs); + cdebug << "TrieDB" << transactionsTrie.root(); + cdebug << "Contents:"; + for (auto const& t: txs) + cdebug << toHex(t); + 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()); diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index da0e56247..cbde3f14e 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -199,7 +199,7 @@ void BlockChain::close() #define IGNORE_EXCEPTIONS(X) try { X; } catch (...) {} -void BlockChain::rebuild(std::string const& _path, std::function const& _progress) +void BlockChain::rebuild(std::string const& _path, std::function const& _progress, bool _prepPoW) { std::string path = _path.empty() ? Defaults::get()->m_dbPath : _path; @@ -252,7 +252,8 @@ void BlockChain::rebuild(std::string const& _path, std::function(h256(u256(d)), m_blockHashes, x_blockHashes, NullBlockHash, oldExtrasDB).value); BlockInfo bi(b); - ProofOfWork::prep(bi); + if (_prepPoW) + ProofOfWork::prep(bi); if (bi.parentHash != lastHash) { @@ -306,7 +307,7 @@ tuple BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st { // _bq.tick(*this); - vector blocks; + vector> blocks; _bq.drain(blocks, _max); h256s fresh; @@ -316,7 +317,7 @@ tuple BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st { try { - auto r = import(block, _stateDB); + auto r = import(block.first, block.second, _stateDB); fresh += r.first; dead += r.second; } @@ -325,14 +326,14 @@ tuple BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st cwarn << "ODD: Import queue contains block with unknown parent." << LogTag::Error << boost::current_exception_diagnostic_information(); // NOTE: don't reimport since the queue should guarantee everything in the right order. // Can't continue - chain bad. - badBlocks.push_back(BlockInfo::headerHash(block)); + badBlocks.push_back(block.first.hash()); } catch (Exception const& _e) { cnote << "Exception while importing block. Someone (Jeff? That you?) seems to be giving us dodgy blocks!" << LogTag::Error << diagnostic_information(_e); // NOTE: don't reimport since the queue should guarantee everything in the right order. // Can't continue - chain bad. - badBlocks.push_back(BlockInfo::headerHash(block)); + badBlocks.push_back(block.first.hash()); } } return make_tuple(fresh, dead, _bq.doneDrain(badBlocks)); @@ -364,18 +365,6 @@ pair BlockChain::attemptImport(bytes const& _block, O ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, ImportRequirements::value _ir) { - //@tidy This is a behemoth of a method - could do to be split into a few smaller ones. - -#if ETH_TIMED_IMPORTS - boost::timer total; - double preliminaryChecks; - double enactment; - double collation; - double writing; - double checkBest; - boost::timer t; -#endif - // VERIFY: populates from the block and checks the block is internally coherent. BlockInfo bi; @@ -383,11 +372,6 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import try #endif { - RLP blockRLP(_block); - - if (!blockRLP.isList()) - BOOST_THROW_EXCEPTION(InvalidBlockFormat() << errinfo_comment("block header needs to be a list") << BadFieldError(0, blockRLP.data().toString())); - bi.populate(&_block); bi.verifyInternals(&_block); } @@ -400,29 +384,46 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import } #endif + return import(bi, _block, _db, _ir); +} + +ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, OverlayDB const& _db, ImportRequirements::value _ir) +{ + //@tidy This is a behemoth of a method - could do to be split into a few smaller ones. + +#if ETH_TIMED_IMPORTS + boost::timer total; + double preliminaryChecks; + double enactment; + double collation; + double writing; + double checkBest; + boost::timer t; +#endif + // Check block doesn't already exist first! - if (isKnown(bi.hash()) && (_ir & ImportRequirements::DontHave)) + if (isKnown(_bi.hash()) && (_ir & ImportRequirements::DontHave)) { - clog(BlockChainNote) << bi.hash() << ": Not new."; + clog(BlockChainNote) << _bi.hash() << ": Not new."; BOOST_THROW_EXCEPTION(AlreadyHaveBlock()); } // Work out its number as the parent's number + 1 - if (!isKnown(bi.parentHash)) + if (!isKnown(_bi.parentHash)) { - clog(BlockChainNote) << bi.hash() << ": Unknown parent " << bi.parentHash; + clog(BlockChainNote) << _bi.hash() << ": Unknown parent " << _bi.parentHash; // We don't know the parent (yet) - discard for now. It'll get resent to us if we find out about its ancestry later on. BOOST_THROW_EXCEPTION(UnknownParent()); } - auto pd = details(bi.parentHash); + auto pd = details(_bi.parentHash); if (!pd) { auto pdata = pd.rlp(); clog(BlockChainDebug) << "Details is returning false despite block known:" << RLP(pdata); - auto parentBlock = block(bi.parentHash); - clog(BlockChainDebug) << "isKnown:" << isKnown(bi.parentHash); - clog(BlockChainDebug) << "last/number:" << m_lastBlockNumber << m_lastBlockHash << bi.number; + auto parentBlock = block(_bi.parentHash); + clog(BlockChainDebug) << "isKnown:" << isKnown(_bi.parentHash); + clog(BlockChainDebug) << "last/number:" << m_lastBlockNumber << m_lastBlockHash << _bi.number; clog(BlockChainDebug) << "Block:" << BlockInfo(parentBlock); clog(BlockChainDebug) << "RLP:" << RLP(parentBlock); clog(BlockChainDebug) << "DATABASE CORRUPTION: CRITICAL FAILURE"; @@ -430,14 +431,14 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import } // Check it's not crazy - if (bi.timestamp > (u256)time(0)) + if (_bi.timestamp > (u256)time(0)) { - clog(BlockChainChat) << bi.hash() << ": Future time " << bi.timestamp << " (now at " << time(0) << ")"; + clog(BlockChainChat) << _bi.hash() << ": Future time " << _bi.timestamp << " (now at " << time(0) << ")"; // Block has a timestamp in the future. This is no good. BOOST_THROW_EXCEPTION(FutureTime()); } - clog(BlockChainChat) << "Attempting import of " << bi.hash() << "..."; + clog(BlockChainChat) << "Attempting import of " << _bi.hash() << "..."; #if ETH_TIMED_IMPORTS preliminaryChecks = t.elapsed(); @@ -457,7 +458,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); - auto tdIncrease = s.enactOn(&_block, bi, *this, _ir); + auto tdIncrease = s.enactOn(&_block, _bi, *this, _ir); BlockLogBlooms blb; BlockReceipts br; @@ -493,22 +494,22 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import // together with an "ensureCachedWithUpdatableLock(l)" method. // This is safe in practice since the caches don't get flushed nearly often enough to be // done here. - details(bi.parentHash); + details(_bi.parentHash); DEV_WRITE_GUARDED(x_details) - m_details[bi.parentHash].children.push_back(bi.hash()); + m_details[_bi.parentHash].children.push_back(_bi.hash()); #if ETH_TIMED_IMPORTS || !ETH_TRUE collation = t.elapsed(); t.restart(); #endif - blocksBatch.Put(toSlice(bi.hash()), (ldb::Slice)ref(_block)); + blocksBatch.Put(toSlice(_bi.hash()), (ldb::Slice)ref(_block)); DEV_READ_GUARDED(x_details) - extrasBatch.Put(toSlice(bi.parentHash, ExtraDetails), (ldb::Slice)dev::ref(m_details[bi.parentHash].rlp())); + extrasBatch.Put(toSlice(_bi.parentHash, ExtraDetails), (ldb::Slice)dev::ref(m_details[_bi.parentHash].rlp())); - extrasBatch.Put(toSlice(bi.hash(), ExtraDetails), (ldb::Slice)dev::ref(BlockDetails((unsigned)pd.number + 1, td, bi.parentHash, {}).rlp())); - extrasBatch.Put(toSlice(bi.hash(), ExtraLogBlooms), (ldb::Slice)dev::ref(blb.rlp())); - extrasBatch.Put(toSlice(bi.hash(), ExtraReceipts), (ldb::Slice)dev::ref(br.rlp())); + extrasBatch.Put(toSlice(_bi.hash(), ExtraDetails), (ldb::Slice)dev::ref(BlockDetails((unsigned)pd.number + 1, td, _bi.parentHash, {}).rlp())); + extrasBatch.Put(toSlice(_bi.hash(), ExtraLogBlooms), (ldb::Slice)dev::ref(blb.rlp())); + extrasBatch.Put(toSlice(_bi.hash(), ExtraReceipts), (ldb::Slice)dev::ref(br.rlp())); #if ETH_TIMED_IMPORTS || !ETH_TRUE writing = t.elapsed(); @@ -526,20 +527,20 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import { clog(BlockChainWarn) << " Malformed block: " << diagnostic_information(_e); _e << errinfo_comment("Malformed block "); - clog(BlockChainWarn) << "Block: " << bi.hash(); - clog(BlockChainWarn) << bi; - clog(BlockChainWarn) << "Block parent: " << bi.parentHash; - clog(BlockChainWarn) << BlockInfo(block(bi.parentHash)); + clog(BlockChainWarn) << "Block: " << _bi.hash(); + clog(BlockChainWarn) << _bi; + clog(BlockChainWarn) << "Block parent: " << _bi.parentHash; + clog(BlockChainWarn) << BlockInfo(block(_bi.parentHash)); throw; } #endif StructuredLogger::chainReceivedNewBlock( - bi.headerHash(WithoutNonce).abridged(), - bi.nonce.abridged(), + _bi.headerHash(WithoutNonce).abridged(), + _bi.nonce.abridged(), currentHash().abridged(), "", // TODO: remote id ?? - bi.parentHash.abridged() + _bi.parentHash.abridged() ); // cnote << "Parent " << bi.parentHash << " has " << details(bi.parentHash).children.size() << " children."; @@ -552,8 +553,8 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import // don't include bi.hash() in treeRoute, since it's not yet in details DB... // just tack it on afterwards. unsigned commonIndex; - tie(route, common, commonIndex) = treeRoute(last, bi.parentHash); - route.push_back(bi.hash()); + tie(route, common, commonIndex) = treeRoute(last, _bi.parentHash); + route.push_back(_bi.hash()); // Most of the time these two will be equal - only when we're doing a chain revert will they not be if (common != last) @@ -565,8 +566,8 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import for (auto i = route.rbegin(); i != route.rend() && *i != common; ++i) { BlockInfo tbi; - if (*i == bi.hash()) - tbi = bi; + if (*i == _bi.hash()) + tbi = _bi; else tbi = BlockInfo(block(*i)); @@ -593,7 +594,7 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import h256s newTransactionAddresses; { bytes blockBytes; - RLP blockRLP(*i == bi.hash() ? _block : (blockBytes = block(*i))); + RLP blockRLP(*i == _bi.hash() ? _block : (blockBytes = block(*i))); TransactionAddress ta; ta.blockHash = tbi.hash(); for (ta.index = 0; ta.index < blockRLP[1].itemCount(); ++ta.index) @@ -609,17 +610,17 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import // FINALLY! change our best hash. { - newLastBlockHash = bi.hash(); - newLastBlockNumber = (unsigned)bi.number; + newLastBlockHash = _bi.hash(); + newLastBlockNumber = (unsigned)_bi.number; } - clog(BlockChainNote) << " Imported and best" << td << " (#" << bi.number << "). Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << route; + clog(BlockChainNote) << " Imported and best" << td << " (#" << _bi.number << "). Has" << (details(_bi.parentHash).children.size() - 1) << "siblings. Route:" << route; StructuredLogger::chainNewHead( - bi.headerHash(WithoutNonce).abridged(), - bi.nonce.abridged(), + _bi.headerHash(WithoutNonce).abridged(), + _bi.nonce.abridged(), currentHash().abridged(), - bi.parentHash.abridged() + _bi.parentHash.abridged() ); } else @@ -630,21 +631,21 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import m_blocksDB->Write(m_writeOptions, &blocksBatch); m_extrasDB->Write(m_writeOptions, &extrasBatch); - if (isKnown(bi.hash()) && !details(bi.hash())) + if (isKnown(_bi.hash()) && !details(_bi.hash())) { clog(BlockChainDebug) << "Known block just inserted has no details."; - clog(BlockChainDebug) << "Block:" << bi; + clog(BlockChainDebug) << "Block:" << _bi; clog(BlockChainDebug) << "DATABASE CORRUPTION: CRITICAL FAILURE"; exit(-1); } try { - State canary(_db, *this, bi.hash(), ImportRequirements::DontHave); + State canary(_db, *this, _bi.hash(), ImportRequirements::DontHave); } catch (...) { clog(BlockChainDebug) << "Failed to initialise State object form imported block."; - clog(BlockChainDebug) << "Block:" << bi; + clog(BlockChainDebug) << "Block:" << _bi; clog(BlockChainDebug) << "DATABASE CORRUPTION: CRITICAL FAILURE"; exit(-1); } diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index 02f3f618a..a67ec9a9c 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -120,6 +120,7 @@ public: /// Import block into disk-backed DB /// @returns the block hashes of any blocks that came into/went out of the canonical block chain. ImportRoute import(bytes const& _block, OverlayDB const& _stateDB, ImportRequirements::value _ir = ImportRequirements::Default); + ImportRoute import(BlockInfo const& _bi, bytes const& _block, OverlayDB const& _stateDB, ImportRequirements::value _ir = ImportRequirements::Default); /// Returns true if the given block is known (though not necessarily a part of the canon chain). bool isKnown(h256 const& _hash) const; @@ -210,7 +211,7 @@ public: /// Run through database and verify all blocks by reevaluating. /// Will call _progress with the progress in this operation first param done, second total. - void rebuild(std::string const& _path, ProgressCallback const& _progress = std::function()); + void rebuild(std::string const& _path, ProgressCallback const& _progress = std::function(), bool _prepPoW = false); /** @returns a tuple of: * - an vector of hashes of all blocks between @a _from and @a _to, all blocks are ordered first by a number of diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index 43d2b4cb8..1632b2fa3 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -20,7 +20,7 @@ */ #include "BlockQueue.h" - +#include #include #include #include @@ -35,6 +35,106 @@ const char* BlockQueueChannel::name() { return EthOrange "[]>"; } const char* BlockQueueChannel::name() { return EthOrange "▣┅▶"; } #endif + +BlockQueue::BlockQueue() +{ + for (unsigned i = 0; i < thread::hardware_concurrency(); ++i) + m_verifiers.emplace_back([=](){ + setThreadName("verifier" + toString(i)); + this->verifierBody(); + }); +} + +BlockQueue::~BlockQueue() +{ + m_deleting = true; + m_moreToVerify.notify_all(); + for (auto& i: m_verifiers) + i.join(); +} + +void BlockQueue::verifierBody() +{ + while (!m_deleting) + { + std::pair work; + + { + unique_lock l(m_verification); + m_moreToVerify.wait(l, [&](){ return !m_unverified.empty() || m_deleting; }); + swap(work, m_unverified.front()); + m_unverified.pop_front(); + BlockInfo bi; + bi.mixHash = work.first; + m_verifying.push_back(make_pair(bi, bytes())); + cdebug << "Verifying" << bi.mixHash; + } + + std::pair res; + swap(work.second, res.second); + try { + res.first.populate(res.second, CheckEverything, work.first); + res.first.verifyInternals(&res.second); + } + catch (...) + { + // bad block. + { + // has to be this order as that's how invariants() assumes. + WriteGuard l2(m_lock); + unique_lock l(m_verification); + m_readySet.erase(work.first); + m_knownBad.insert(work.first); + } + + unique_lock l(m_verification); + for (auto it = m_verifying.begin(); it != m_verifying.end(); ++it) + if (it->first.mixHash == work.first) + { + cdebug << "Cancel verifying" << work.first; + m_verifying.erase(it); + goto OK1; + } + cwarn << "GAA BlockQueue corrupt: job cancelled but cannot be found in m_verifying queue."; + OK1:; + continue; + } + + bool ready = false; + { + unique_lock l(m_verification); + if (m_verifying.front().first.mixHash == work.first) + { + // we're next! + cdebug << "Verifyied" << work.first; + m_verifying.pop_front(); + m_verified.push_back(move(res)); + while (m_verifying.size() && !m_verifying.front().second.empty()) + { + cdebug << "Pre-verified" << m_verifying.front().first.hash(); + m_verified.push_back(move(m_verifying.front())); + m_verifying.pop_front(); + } + ready = true; + } + else + { + for (auto& i: m_verifying) + if (i.first.mixHash == work.first) + { + cdebug << "Delay-verified" << work.first << " (replacing with " << res << ")"; + i = move(res); + goto OK; + } + cwarn << "GAA BlockQueue corrupt: job finished but cannot be found in m_verifying queue."; + OK:; + } + } + if (ready) + m_onReady(); + } +} + ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, bool _isOurs) { // Check if we already know this block. @@ -110,11 +210,13 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo { // If valid, append to blocks. cblockq << "OK - ready for chain insertion."; - m_ready.push_back(make_pair(h, _block.toBytes())); + DEV_GUARDED(m_verification) + m_unverified.push_back(make_pair(h, _block.toBytes())); + m_moreToVerify.notify_one(); m_readySet.insert(h); noteReady_WITH_LOCK(h); - m_onReady(); + return ImportResult::Success; } } @@ -127,18 +229,19 @@ bool BlockQueue::doneDrain(h256s const& _bad) m_drainingSet.clear(); if (_bad.size()) { - vector> old; - swap(m_ready, old); + vector> old; + DEV_GUARDED(m_verification) + swap(m_verified, old); for (auto& b: old) { - BlockInfo bi(b.second); - if (m_knownBad.count(bi.parentHash)) + if (m_knownBad.count(b.first.parentHash)) { - m_knownBad.insert(b.first); - m_readySet.erase(b.first); + m_knownBad.insert(b.first.hash()); + m_readySet.erase(b.first.hash()); } else - m_ready.push_back(std::move(b)); + DEV_GUARDED(m_verification) + m_verified.push_back(std::move(b)); } } m_knownBad += _bad; @@ -197,62 +300,73 @@ QueueStatus BlockQueue::blockStatus(h256 const& _h) const QueueStatus::Unknown; } -void BlockQueue::drain(std::vector& o_out, unsigned _max) +void BlockQueue::drain(std::vector>& o_out, unsigned _max) { WriteGuard l(m_lock); DEV_INVARIANT_CHECK; if (m_drainingSet.empty()) { - o_out.resize(min(_max, m_ready.size())); - for (unsigned i = 0; i < o_out.size(); ++i) - swap(o_out[i], m_ready[i].second); - m_ready.erase(m_ready.begin(), advanced(m_ready.begin(), o_out.size())); + DEV_GUARDED(m_verification) + { + o_out.resize(min(_max, m_verified.size())); + for (unsigned i = 0; i < o_out.size(); ++i) + swap(o_out[i], m_verified[i]); + m_verified.erase(m_verified.begin(), advanced(m_verified.begin(), o_out.size())); + } for (auto const& bs: o_out) { // TODO: @optimise use map rather than vector & set. - auto h = BlockInfo::headerHash(bs); + auto h = bs.first.hash(); m_drainingSet.insert(h); m_readySet.erase(h); } -// swap(o_out, m_ready); -// swap(m_drainingSet, m_readySet); } } bool BlockQueue::invariants() const { - return m_readySet.size() == m_ready.size(); + Guard l(m_verification); + return m_readySet.size() == m_verified.size() + m_unverified.size() + m_verifying.size(); } void BlockQueue::noteReady_WITH_LOCK(h256 const& _good) { DEV_INVARIANT_CHECK; list goodQueue(1, _good); + bool notify = false; while (!goodQueue.empty()) { auto r = m_unknown.equal_range(goodQueue.front()); goodQueue.pop_front(); for (auto it = r.first; it != r.second; ++it) { - m_ready.push_back(it->second); + DEV_GUARDED(m_verification) + m_unverified.push_back(it->second); auto newReady = it->second.first; m_unknownSet.erase(newReady); m_readySet.insert(newReady); goodQueue.push_back(newReady); + notify = true; } m_unknown.erase(r.first, r.second); } + if (notify) + m_moreToVerify.notify_all(); } void BlockQueue::retryAllUnknown() { + WriteGuard l(m_lock); DEV_INVARIANT_CHECK; for (auto it = m_unknown.begin(); it != m_unknown.end(); ++it) { - m_ready.push_back(it->second); + DEV_GUARDED(m_verification) + m_unverified.push_back(it->second); auto newReady = it->second.first; m_unknownSet.erase(newReady); m_readySet.insert(newReady); + m_moreToVerify.notify_one(); } m_unknown.clear(); + m_moreToVerify.notify_all(); } diff --git a/libethereum/BlockQueue.h b/libethereum/BlockQueue.h index a4e44b390..ba515b409 100644 --- a/libethereum/BlockQueue.h +++ b/libethereum/BlockQueue.h @@ -21,12 +21,15 @@ #pragma once +#include +#include #include #include #include #include #include #include +#include namespace dev { @@ -41,7 +44,9 @@ struct BlockQueueChannel: public LogChannel { static const char* name(); static struct BlockQueueStatus { - size_t ready; + size_t verified; + size_t verifying; + size_t unverified; size_t future; size_t unknown; size_t bad; @@ -64,6 +69,9 @@ enum class QueueStatus class BlockQueue: HasInvariants { public: + BlockQueue(); + ~BlockQueue(); + /// Import a block into the queue. ImportResult import(bytesConstRef _tx, BlockChain const& _bc, bool _isOurs = false); @@ -72,7 +80,7 @@ public: /// Grabs at most @a _max of the blocks that are ready, giving them in the correct order for insertion into the chain. /// Don't forget to call doneDrain() once you're done importing. - void drain(std::vector& o_out, unsigned _max); + void drain(std::vector>& o_out, unsigned _max); /// Must be called after a drain() call. Notes that the drained blocks have been imported into the blockchain, so we can forget about them. /// @returns true iff there are additional blocks ready to be processed. @@ -85,16 +93,16 @@ public: void retryAllUnknown(); /// Get information on the items queued. - std::pair items() const { ReadGuard l(m_lock); return std::make_pair(m_ready.size(), m_unknown.size()); } + std::pair items() const { ReadGuard l(m_lock); return std::make_pair(m_verified.size(), m_unknown.size()); } /// Clear everything. - void clear() { WriteGuard l(m_lock); DEV_INVARIANT_CHECK; m_readySet.clear(); m_drainingSet.clear(); m_ready.clear(); m_unknownSet.clear(); m_unknown.clear(); m_future.clear(); } + void clear() { WriteGuard l(m_lock); DEV_INVARIANT_CHECK; Guard l2(m_verification); m_readySet.clear(); m_drainingSet.clear(); m_verified.clear(); m_unverified.clear(); m_unknownSet.clear(); m_unknown.clear(); m_future.clear(); } /// Return first block with an unknown parent. h256 firstUnknown() const { ReadGuard l(m_lock); return m_unknownSet.size() ? *m_unknownSet.begin() : h256(); } /// Get some infomration on the current status. - BlockQueueStatus status() const { ReadGuard l(m_lock); return BlockQueueStatus{m_ready.size(), m_future.size(), m_unknown.size(), m_knownBad.size()}; } + BlockQueueStatus status() const { ReadGuard l(m_lock); Guard l2(m_verification); return BlockQueueStatus{m_verified.size(), m_verifying.size(), m_unverified.size(), m_future.size(), m_unknown.size(), m_knownBad.size()}; } /// Get some infomration on the given block's status regarding us. QueueStatus blockStatus(h256 const& _h) const; @@ -106,15 +114,25 @@ private: bool invariants() const override; - mutable boost::shared_mutex m_lock; ///< General lock. + void verifierBody(); + + mutable boost::shared_mutex m_lock; ///< General lock for the sets, m_future and m_unknown. 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_readySet; ///< All blocks 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. + + mutable Mutex m_verification; ///< Mutex that allows writing to m_verified, m_verifying and m_unverified. + std::condition_variable m_moreToVerify; ///< Signaled when m_unverified has a new entry. + std::vector> m_verified; ///< List of blocks, in correct order, verified and ready for chain-import. + std::deque> m_verifying; ///< List of blocks being verified; as long as the second component (bytes) is empty, it's not finished. + std::deque> m_unverified; ///< List of blocks, in correct order, ready for verification. + + std::vector m_verifiers; ///< Threads who only verify. + bool m_deleting = false; ///< Exit condition for verifiers. }; } diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index cfa271cf6..8dc666bb5 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -57,7 +57,7 @@ void ClientBase::submitTransaction(Secret _secret, u256 _value, Address _dest, b m_tq.import(t.rlp()); StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged()); - cnote << "New transaction " << t; + cnote << "New transaction " << t << "(maxNonce for sender" << a << "is" << m_tq.maxNonce(a) << ")"; } Address ClientBase::submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 654dca8d7..b9e548ea3 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -516,10 +517,10 @@ pair State::sync(BlockChain const& _bc, TransactionQu cnote << i.first << "Dropping old transaction (nonce too low)"; _tq.drop(i.first); } - else if (got > req + 25) + else if (got > req + _tq.waiting(i.second.sender())) { // too new - cnote << i.first << "Dropping new transaction (> 25 nonces ahead)"; + cnote << i.first << "Dropping new transaction (too many nonces ahead)"; _tq.drop(i.first); } else @@ -534,7 +535,12 @@ pair State::sync(BlockChain const& _bc, TransactionQu _tq.drop(i.first); } else - _tq.setFuture(i); + { + // Temporarily no gas left in current block. + // OPTIMISE: could note this and then we don't evaluate until a block that does have the gas left. + // for now, just leave alone. +// _tq.setFuture(i); + } } catch (Exception const& _e) { @@ -592,34 +598,33 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement LastHashes lh = _bc.lastHashes((unsigned)m_previousBlock.number); RLP rlp(_block); + vector receipts; + // All ok with the block generally. Play back the transactions now... unsigned i = 0; for (auto const& tr: rlp[1]) { - RLPStream k; - k << i; - - transactionsTrie.insert(&k.out(), tr.data()); execute(lh, Transaction(tr.data(), CheckTransaction::Everything)); - - RLPStream receiptrlp; - m_receipts.back().streamRLP(receiptrlp); - receiptsTrie.insert(&k.out(), &receiptrlp.out()); + RLPStream receiptRLP; + m_receipts.back().streamRLP(receiptRLP); + receipts.push_back(receiptRLP.out()); ++i; } - if (receiptsTrie.root() != m_currentBlock.receiptsRoot) + auto receiptsRoot = orderedTrieRoot(receipts); + + if (receiptsRoot != m_currentBlock.receiptsRoot) { cwarn << "Bad receipts state root."; - cwarn << "Expected: " << toString(receiptsTrie.root()) << " received: " << toString(m_currentBlock.receiptsRoot); + cwarn << "Expected: " << toString(receiptsRoot) << " received: " << toString(m_currentBlock.receiptsRoot); cwarn << "Block:" << toHex(_block); cwarn << "Block RLP:" << rlp; - cwarn << "Calculated: " << receiptsTrie.root(); + cwarn << "Calculated: " << receiptsRoot; for (unsigned j = 0; j < i; ++j) { RLPStream k; k << j; - auto b = asBytes(receiptsTrie.at(&k.out())); + auto b = receipts[j]; cwarn << j << ": "; cwarn << "RLP: " << RLP(b); cwarn << "Hex: " << toHex(b); @@ -835,6 +840,9 @@ void State::commitToMine(BlockChain const& _bc) } } + // TODO: move over to using TrieHash + + MemoryDB tm; GenericTrieDB transactionsTrie(&tm); transactionsTrie.init(); diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 11104705c..76c486d50 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -35,20 +35,26 @@ ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallb // Check if we already know this transaction. h256 h = sha3(_transactionRLP); + Transaction t; + ImportResult ir; + { UpgradableGuard l(m_lock); - auto ir = check_WITH_LOCK(h, _ik); + ir = check_WITH_LOCK(h, _ik); if (ir != ImportResult::Success) return ir; try { - Transaction t(_transactionRLP, CheckTransaction::Everything); + t = Transaction(_transactionRLP, CheckTransaction::Everything); UpgradeGuard ul(l); - return manageImport_WITH_LOCK(h, t, _cb); + ir = manageImport_WITH_LOCK(h, t, _cb); } catch (...) { return ImportResult::Malformed; } + } +// cdebug << "import-END: Nonce of" << t.sender() << "now" << maxNonce(t.sender()); + return ir; } ImportResult TransactionQueue::check_WITH_LOCK(h256 const& _h, IfDropped _ik) @@ -67,15 +73,23 @@ ImportResult TransactionQueue::import(Transaction const& _transaction, ImportCal // Check if we already know this transaction. h256 h = _transaction.sha3(WithSignature); - UpgradableGuard l(m_lock); - // TODO: keep old transactions around and check in State for nonce validity +// cdebug << "import-BEGIN: Nonce of sender" << maxNonce(_transaction.sender()); + ImportResult ret; + { + UpgradableGuard l(m_lock); + // TODO: keep old transactions around and check in State for nonce validity - auto ir = check_WITH_LOCK(h, _ik); - if (ir != ImportResult::Success) - return ir; + auto ir = check_WITH_LOCK(h, _ik); + if (ir != ImportResult::Success) + return ir; - UpgradeGuard ul(l); - return manageImport_WITH_LOCK(h, _transaction, _cb); + { + UpgradeGuard ul(l); + ret = manageImport_WITH_LOCK(h, _transaction, _cb); + } + } +// cdebug << "import-END: Nonce of" << _transaction.sender() << "now" << maxNonce(_transaction.sender()); + return ret; } ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transaction const& _transaction, ImportCallback const& _cb) @@ -110,62 +124,95 @@ ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transactio u256 TransactionQueue::maxNonce(Address const& _a) const { - cdebug << "txQ::maxNonce" << _a; +// cdebug << "txQ::maxNonce" << _a; ReadGuard l(m_lock); u256 ret = 0; auto r = m_senders.equal_range(_a); for (auto it = r.first; it != r.second; ++it) - { - cdebug << it->first << "1+" << m_current.at(it->second).nonce(); - DEV_IGNORE_EXCEPTIONS(ret = max(ret, m_current.at(it->second).nonce() + 1)); - } + if (m_current.count(it->second)) + { +// cdebug << it->first << "1+" << m_current.at(it->second).nonce(); + ret = max(ret, m_current.at(it->second).nonce() + 1); + } + else if (m_future.count(it->second)) + { +// cdebug << it->first << "1+" << m_future.at(it->second).nonce(); + ret = max(ret, m_future.at(it->second).nonce() + 1); + } + else + { + cwarn << "ERRROR!!!!! m_senders references non-current transaction"; + cwarn << "Sender" << it->first << "has transaction" << it->second; + cwarn << "Count of m_current for" << it->second << "is" << m_current.count(it->second); + } return ret; } void TransactionQueue::insertCurrent_WITH_LOCK(std::pair const& _p) { - cdebug << "txQ::insertCurrent" << _p.first << _p.second.sender() << _p.second.nonce(); +// cdebug << "txQ::insertCurrent" << _p.first << _p.second.sender() << _p.second.nonce(); m_senders.insert(make_pair(_p.second.sender(), _p.first)); + if (m_current.count(_p.first)) + cwarn << "Transaction hash" << _p.first << "already in current?!"; m_current.insert(_p); } -bool TransactionQueue::removeCurrent_WITH_LOCK(h256 const& _txHash) +bool TransactionQueue::remove_WITH_LOCK(h256 const& _txHash) { - cdebug << "txQ::removeCurrent" << _txHash; - if (m_current.count(_txHash)) +// cdebug << "txQ::remove" << _txHash; + for (std::unordered_map* pool: { &m_current, &m_future }) { - auto r = m_senders.equal_range(m_current[_txHash].sender()); - for (auto it = r.first; it != r.second; ++it) - if (it->second == _txHash) - { - cdebug << "=> sender" << it->first; - m_senders.erase(it); - break; - } - cdebug << "=> nonce" << m_current[_txHash].nonce(); - m_current.erase(_txHash); - return true; + auto pit = pool->find(_txHash); + if (pit != pool->end()) + { + auto r = m_senders.equal_range(pit->second.sender()); + for (auto i = r.first; i != r.second; ++i) + if (i->second == _txHash) + { + m_senders.erase(i); + break; + } + cdebug << "=> nonce" << pit->second.nonce(); + pool->erase(pit); + return true; + } } return false; } +unsigned TransactionQueue::waiting(Address const& _a) const +{ + auto it = m_senders.equal_range(_a); + unsigned ret = 0; + for (auto i = it.first; i != it.second; ++i, ++ret) {} + return ret; +} + void TransactionQueue::setFuture(std::pair const& _t) { +// cdebug << "txQ::setFuture" << _t.first; WriteGuard l(m_lock); if (m_current.count(_t.first)) { - m_unknown.insert(make_pair(_t.second.sender(), _t)); + m_future.insert(_t); m_current.erase(_t.first); } } void TransactionQueue::noteGood(std::pair const& _t) { +// cdebug << "txQ::noteGood" << _t.first; WriteGuard l(m_lock); - auto r = m_unknown.equal_range(_t.second.sender()); + auto r = m_senders.equal_range(_t.second.sender()); for (auto it = r.first; it != r.second; ++it) - m_current.insert(it->second); - m_unknown.erase(r.first, r.second); + { + auto fit = m_future.find(it->second); + if (fit != m_future.end()) + { + m_current.insert(*fit); + m_future.erase(fit); + } + } } void TransactionQueue::drop(h256 const& _txHash) @@ -179,13 +226,5 @@ void TransactionQueue::drop(h256 const& _txHash) m_dropped.insert(_txHash); m_known.erase(_txHash); - if (!removeCurrent_WITH_LOCK(_txHash)) - { - for (auto i = m_unknown.begin(); i != m_unknown.end(); ++i) - if (i->second.first == _txHash) - { - m_unknown.erase(i); - break; - } - } + remove_WITH_LOCK(_txHash); } diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index 50fcea574..e91a12360 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -55,14 +55,15 @@ public: void drop(h256 const& _txHash); + unsigned waiting(Address const& _a) const; 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()); } + std::pair items() const { ReadGuard l(m_lock); return std::make_pair(m_current.size(), m_future.size()); } u256 maxNonce(Address const& _a) const; void setFuture(std::pair const& _t); void noteGood(std::pair const& _t); - void clear() { WriteGuard l(m_lock); m_known.clear(); m_current.clear(); m_unknown.clear(); } + void clear() { WriteGuard l(m_lock); m_senders.clear(); m_known.clear(); m_current.clear(); m_future.clear(); } template Handler onReady(T const& _t) { return m_onReady.add(_t); } private: @@ -70,15 +71,15 @@ private: ImportResult manageImport_WITH_LOCK(h256 const& _h, Transaction const& _transaction, ImportCallback const& _cb); void insertCurrent_WITH_LOCK(std::pair const& _p); - bool removeCurrent_WITH_LOCK(h256 const& _txHash); + bool remove_WITH_LOCK(h256 const& _txHash); mutable SharedMutex m_lock; ///< General lock. h256Hash m_known; ///< Hashes of transactions in both sets. + std::unordered_multimap m_senders; ///< Mapping from the sender address to the transaction hash; useful for determining the nonce of a given sender. 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_future; ///< For transactions that have a future nonce; we re-insert into current 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/test/libdevcrypto/trie.cpp b/test/libdevcrypto/trie.cpp index d41739a01..c53617772 100644 --- a/test/libdevcrypto/trie.cpp +++ b/test/libdevcrypto/trie.cpp @@ -28,7 +28,7 @@ #include "../JsonSpiritHeaders.h" #include #include -#include "TrieHash.h" +#include #include "MemTrie.h" #include "../TestHelper.h" From b0dba6b5599214550ec553aeaf11bf0ce6121772 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 17 May 2015 21:23:31 +0200 Subject: [PATCH 106/157] Version bump push all valid "ready" transactions to the network asap. --- libdevcore/Common.cpp | 2 +- libethereum/BlockQueue.cpp | 7 ++----- libethereum/TransactionQueue.cpp | 10 ++++++++++ libethereum/TransactionQueue.h | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 1ffa66f14..7171c4a2b 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -28,7 +28,7 @@ using namespace dev; namespace dev { -char const* Version = "0.9.21"; +char const* Version = "0.9.22"; const u256 UndefinedU256 = ~(u256)0; diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index 1632b2fa3..43a3d1caf 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -62,12 +62,13 @@ void BlockQueue::verifierBody() { unique_lock l(m_verification); m_moreToVerify.wait(l, [&](){ return !m_unverified.empty() || m_deleting; }); + if (m_deleting) + return; swap(work, m_unverified.front()); m_unverified.pop_front(); BlockInfo bi; bi.mixHash = work.first; m_verifying.push_back(make_pair(bi, bytes())); - cdebug << "Verifying" << bi.mixHash; } std::pair res; @@ -91,7 +92,6 @@ void BlockQueue::verifierBody() for (auto it = m_verifying.begin(); it != m_verifying.end(); ++it) if (it->first.mixHash == work.first) { - cdebug << "Cancel verifying" << work.first; m_verifying.erase(it); goto OK1; } @@ -106,12 +106,10 @@ void BlockQueue::verifierBody() if (m_verifying.front().first.mixHash == work.first) { // we're next! - cdebug << "Verifyied" << work.first; m_verifying.pop_front(); m_verified.push_back(move(res)); while (m_verifying.size() && !m_verifying.front().second.empty()) { - cdebug << "Pre-verified" << m_verifying.front().first.hash(); m_verified.push_back(move(m_verifying.front())); m_verifying.pop_front(); } @@ -122,7 +120,6 @@ void BlockQueue::verifierBody() for (auto& i: m_verifying) if (i.first.mixHash == work.first) { - cdebug << "Delay-verified" << work.first << " (replacing with " << res << ")"; i = move(res); goto OK; } diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 76c486d50..40a149ebf 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -92,6 +92,16 @@ ImportResult TransactionQueue::import(Transaction const& _transaction, ImportCal return ret; } +std::unordered_map TransactionQueue::transactions() const +{ + ReadGuard l(m_lock); + auto ret = m_current; + for (auto const& i: m_future) + if (i.second.nonce() < maxNonce(i.second.sender())) + ret.insert(i); + return ret; +} + ImportResult TransactionQueue::manageImport_WITH_LOCK(h256 const& _h, Transaction const& _transaction, ImportCallback const& _cb) { try diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index e91a12360..6036caa83 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -56,7 +56,7 @@ public: void drop(h256 const& _txHash); unsigned waiting(Address const& _a) const; - std::unordered_map transactions() const { ReadGuard l(m_lock); return m_current; } + std::unordered_map transactions() const; std::pair items() const { ReadGuard l(m_lock); return std::make_pair(m_current.size(), m_future.size()); } u256 maxNonce(Address const& _a) const; From 3c410cf00883b38efe188e38af9bbc783197951a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 17 May 2015 21:45:51 +0200 Subject: [PATCH 107/157] Lockup fix. --- libethereum/TransactionQueue.cpp | 7 ++++++- libethereum/TransactionQueue.h | 1 + libp2p/Host.cpp | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 40a149ebf..785e16c2d 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -97,7 +97,7 @@ std::unordered_map TransactionQueue::transactions() const ReadGuard l(m_lock); auto ret = m_current; for (auto const& i: m_future) - if (i.second.nonce() < maxNonce(i.second.sender())) + if (i.second.nonce() < maxNonce_WITH_LOCK(i.second.sender())) ret.insert(i); return ret; } @@ -136,6 +136,11 @@ u256 TransactionQueue::maxNonce(Address const& _a) const { // cdebug << "txQ::maxNonce" << _a; ReadGuard l(m_lock); + return maxNonce_WITH_LOCK(_a); +} + +u256 TransactionQueue::maxNonce_WITH_LOCK(Address const& _a) const +{ u256 ret = 0; auto r = m_senders.equal_range(_a); for (auto it = r.first; it != r.second; ++it) diff --git a/libethereum/TransactionQueue.h b/libethereum/TransactionQueue.h index 6036caa83..a07efb848 100644 --- a/libethereum/TransactionQueue.h +++ b/libethereum/TransactionQueue.h @@ -72,6 +72,7 @@ private: void insertCurrent_WITH_LOCK(std::pair const& _p); bool remove_WITH_LOCK(h256 const& _txHash); + u256 maxNonce_WITH_LOCK(Address const& _a) const; mutable SharedMutex m_lock; ///< General lock. h256Hash m_known; ///< Hashes of transactions in both sets. diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 2f139fd3d..9c3e629d4 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -392,7 +392,7 @@ string Host::pocHost() std::unordered_map const& Host::pocHosts() { static const std::unordered_map c_ret = { -// { Public(""), "poc-9.ethdev.com:30303" }, + { Public("487611428e6c99a11a9795a6abe7b529e81315ca6aad66e2a2fc76e3adf263faba0d35466c2f8f68d561dbefa8878d4df5f1f2ddb1fbeab7f42ffb8cd328bd4a"), "poc-9.ethdev.com:30303" }, { Public("a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c"), "52.16.188.185:30303" }, { Public("7f25d3eab333a6b98a8b5ed68d962bb22c876ffcd5561fca54e3c2ef27f754df6f7fd7c9b74cc919067abac154fb8e1f8385505954f161ae440abc355855e034"), "54.207.93.166:30303" } }; From 68099a7c8ea16052d5cb14326345e2f89676a366 Mon Sep 17 00:00:00 2001 From: subtly Date: Sun, 17 May 2015 23:10:50 +0200 Subject: [PATCH 108/157] Normalize ethash filepath for macos to be same as others. --- ethminer/main.cpp | 5 ++++- libethash/io_posix.c | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/ethminer/main.cpp b/ethminer/main.cpp index bcb33915f..c5fa968a7 100644 --- a/ethminer/main.cpp +++ b/ethminer/main.cpp @@ -251,7 +251,10 @@ void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod) Json::Value v = rpc.eth_getWork(); h256 hh(v[0].asString()); h256 newSeedHash(v[1].asString()); - if (hh != current.headerHash && !!EthashAux::full(newSeedHash, true)) + if (!EthashAux::full(newSeedHash, true)) + BOOST_THROW_EXCEPTION(DAGCreationFailure()); + + if (hh != current.headerHash) { current.headerHash = hh; current.seedHash = newSeedHash; diff --git a/libethash/io_posix.c b/libethash/io_posix.c index 7f03d5482..b030748a9 100644 --- a/libethash/io_posix.c +++ b/libethash/io_posix.c @@ -26,6 +26,10 @@ #include #include #include +#if defined(__APPLE__) +#include +#include +#endif FILE* ethash_fopen(char const* file_name, char const* mode) { @@ -86,9 +90,22 @@ bool ethash_file_size(FILE* f, size_t* ret_size) bool ethash_get_default_dirname(char* strbuf, size_t buffsize) { +#if defined(__APPLE__) + static const char dir_suffix[] = "Ethash/"; + strbuf[0] = '\0'; + char* home_dir = getenv("HOME"); + if (!home_dir || strlen(home_dir) == 0) + { + struct passwd* pwd = getpwuid(getuid()); + if (pwd) + home_dir = pwd->pw_dir; + } +#else static const char dir_suffix[] = ".ethash/"; strbuf[0] = '\0'; char* home_dir = getenv("HOME"); +#endif + size_t len = strlen(home_dir); if (!ethash_strncat(strbuf, buffsize, home_dir, len)) { return false; From 6bce6400ff82b019e5033e64add48c0ca13c46a9 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 17 May 2015 23:11:43 +0200 Subject: [PATCH 109/157] Fix lockup. --- libethcore/Common.cpp | 5 +++-- libethereum/Client.cpp | 16 ++++++++-------- libethereum/TransactionQueue.cpp | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/libethcore/Common.cpp b/libethcore/Common.cpp index 0b36ca5fa..c74aeba5e 100644 --- a/libethcore/Common.cpp +++ b/libethcore/Common.cpp @@ -36,11 +36,12 @@ namespace eth { const unsigned c_protocolVersion = 60; -const unsigned c_minorProtocolVersion = 2; #if ETH_FATDB -const unsigned c_databaseBaseVersion = 10; +const unsigned c_minorProtocolVersion = 3; +const unsigned c_databaseBaseVersion = 9; const unsigned c_databaseVersionModifier = 1; #else +const unsigned c_minorProtocolVersion = 2; const unsigned c_databaseBaseVersion = 9; const unsigned c_databaseVersionModifier = 0; #endif diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 6d934f3ad..6d5e39e39 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -461,13 +461,13 @@ ProofOfWork::WorkPackage Client::getWork() bool Client::submitWork(ProofOfWork::Solution const& _solution) { bytes newBlock; - DEV_TIMED(working) DEV_WRITE_GUARDED(x_working) + DEV_WRITE_GUARDED(x_working) if (!m_working.completeMine(_solution)) return false; DEV_READ_GUARDED(x_working) { - DEV_TIMED(post) DEV_WRITE_GUARDED(x_postMine) + DEV_WRITE_GUARDED(x_postMine) m_postMine = m_working; newBlock = m_working.blockData(); } @@ -499,14 +499,14 @@ void Client::syncTransactionQueue() h256Hash changeds; TransactionReceipts newPendingReceipts; - DEV_TIMED(working) DEV_WRITE_GUARDED(x_working) + DEV_WRITE_GUARDED(x_working) tie(newPendingReceipts, m_syncTransactionQueue) = m_working.sync(m_bc, m_tq, *m_gp); if (newPendingReceipts.empty()) return; DEV_READ_GUARDED(x_working) - DEV_TIMED(post) DEV_WRITE_GUARDED(x_postMine) + DEV_WRITE_GUARDED(x_postMine) m_postMine = m_working; DEV_READ_GUARDED(x_postMine) @@ -574,7 +574,7 @@ void Client::onChainChanged(ImportRoute const& _ir) DEV_WRITE_GUARDED(x_preMine) m_preMine = newPreMine; - DEV_TIMED(working) DEV_WRITE_GUARDED(x_working) + DEV_WRITE_GUARDED(x_working) m_working = newPreMine; DEV_READ_GUARDED(x_postMine) for (auto const& t: m_postMine.pending()) @@ -584,7 +584,7 @@ void Client::onChainChanged(ImportRoute const& _ir) if (ir != ImportResult::Success) onTransactionQueueReady(); } - DEV_READ_GUARDED(x_working) DEV_TIMED(post) DEV_WRITE_GUARDED(x_postMine) + DEV_READ_GUARDED(x_working) DEV_WRITE_GUARDED(x_postMine) m_postMine = m_working; changeds.insert(PendingChangedFilter); @@ -609,11 +609,11 @@ void Client::onPostStateChanged() cnote << "Post state changed: Restarting mining..."; if (isMining() || remoteActive()) { - DEV_TIMED(working) DEV_WRITE_GUARDED(x_working) + DEV_WRITE_GUARDED(x_working) m_working.commitToMine(m_bc); DEV_READ_GUARDED(x_working) { - DEV_TIMED(post) DEV_WRITE_GUARDED(x_postMine) + DEV_WRITE_GUARDED(x_postMine) m_postMine = m_working; m_miningInfo = m_postMine.info(); } diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 785e16c2d..e488805d9 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -187,7 +187,7 @@ bool TransactionQueue::remove_WITH_LOCK(h256 const& _txHash) m_senders.erase(i); break; } - cdebug << "=> nonce" << pit->second.nonce(); +// cdebug << "=> nonce" << pit->second.nonce(); pool->erase(pit); return true; } From cbb5e640ef6646abf8244570c9a6f803fe9f1891 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 18 May 2015 00:26:09 +0200 Subject: [PATCH 110/157] more blockchain import optimizations --- libethcore/EthashAux.cpp | 4 ++-- libethcore/EthashAux.h | 2 +- libethereum/BlockChain.cpp | 2 +- libethereum/BlockQueue.cpp | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index 9bb2c4aa9..e01372452 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -101,13 +101,13 @@ uint64_t EthashAux::number(h256 const& _seedHash) void EthashAux::killCache(h256 const& _s) { - RecursiveGuard l(x_lights); + WriteGuard l(x_lights); m_lights.erase(_s); } EthashAux::LightType EthashAux::light(h256 const& _seedHash) { - RecursiveGuard l(get()->x_lights); + ReadGuard l(get()->x_lights); LightType ret = get()->m_lights[_seedHash]; return ret ? ret : (get()->m_lights[_seedHash] = make_shared(_seedHash)); } diff --git a/libethcore/EthashAux.h b/libethcore/EthashAux.h index 92ca52097..3f876f442 100644 --- a/libethcore/EthashAux.h +++ b/libethcore/EthashAux.h @@ -88,7 +88,7 @@ private: static EthashAux* s_this; - RecursiveMutex x_lights; + SharedMutex x_lights; std::unordered_map> m_lights; Mutex x_fulls; diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index cbde3f14e..7838e432d 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -317,7 +317,7 @@ tuple BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st { try { - auto r = import(block.first, block.second, _stateDB); + auto r = import(block.first, block.second, _stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce); fresh += r.first; dead += r.second; } diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index 43a3d1caf..8fa7b6cca 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -38,7 +38,8 @@ const char* BlockQueueChannel::name() { return EthOrange "▣┅▶"; } BlockQueue::BlockQueue() { - for (unsigned i = 0; i < thread::hardware_concurrency(); ++i) + unsigned verifierThreads = std::max(thread::hardware_concurrency(), 3U) - 2U; + for (unsigned i = 0; i < verifierThreads; ++i) m_verifiers.emplace_back([=](){ setThreadName("verifier" + toString(i)); this->verifierBody(); From 3f979d856f986abaac32fde3ed501931d97b596b Mon Sep 17 00:00:00 2001 From: subtly Date: Mon, 18 May 2015 02:56:58 +0200 Subject: [PATCH 111/157] Add deque for windows to compile. --- libethereum/BlockQueue.h | 1 + libwhisper/WhisperPeer.cpp | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libethereum/BlockQueue.h b/libethereum/BlockQueue.h index ba515b409..c865bac32 100644 --- a/libethereum/BlockQueue.h +++ b/libethereum/BlockQueue.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include diff --git a/libwhisper/WhisperPeer.cpp b/libwhisper/WhisperPeer.cpp index 9bef25140..7bcdfe8aa 100644 --- a/libwhisper/WhisperPeer.cpp +++ b/libwhisper/WhisperPeer.cpp @@ -66,10 +66,8 @@ bool WhisperPeer::interpret(unsigned _id, RLP const& _r) } case MessagesPacket: { - unsigned n = 0; for (auto i: _r) - if (n++) - host()->inject(Envelope(i), this); + host()->inject(Envelope(i), this); break; } default: From 953be7886b5681f0fa8ecde94b1fdb8c25afbfd4 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 18 May 2015 08:57:00 +0200 Subject: [PATCH 112/157] Move Farm to ethcore and rejig build to allow ethminer-only build. --- CMakeLists.txt | 66 ++++++++++++++++++++++-------- ethminer/CMakeLists.txt | 7 +--- ethminer/main.cpp | 12 ++---- exp/main.cpp | 2 +- libethcore/CMakeLists.txt | 2 +- {libethereum => libethcore}/Farm.h | 0 libethereum/Client.h | 2 +- libethereum/Farm.cpp | 0 8 files changed, 57 insertions(+), 34 deletions(-) rename {libethereum => libethcore}/Farm.h (100%) delete mode 100644 libethereum/Farm.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 289cecad8..aafdad099 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ option(USENPM "Use npm to recompile ethereum.js if it was changed" OFF) option(PROFILING "Build in support for profiling" OFF) set(BUNDLE "none" CACHE STRING "Predefined bundle of software to build (none, full, user, tests, minimal).") +option(MINER "Build the miner component" ON) option(SOLIDITY "Build the Solidity language components" ON) option(SERPENT "Build the Serpent language components" ON) option(TOOLS "Build the tools components" ON) @@ -187,6 +188,7 @@ eth_format_option(VMTRACE) eth_format_option(EVMJIT) eth_format_option(FATDB) eth_format_option(JSONRPC) +eth_format_option(MINER) eth_format_option(USENPM) eth_format_option(PROFILING) eth_format_option(SOLIDITY) @@ -249,6 +251,16 @@ elseif (BUNDLE STREQUAL "user") set(NCURSES ${DECENT_PLATFORM}) set(TOOLS ON) set(TESTS OFF) +elseif (BUNDLE STREQUAL "miner") + set(SERPENT OFF) + set(SOLIDITY OFF) + set(USENPM OFF) + set(GUI OFF) + set(NCURSES OFF) + set(TOOLS OFF) + set(TESTS OFF) + set(MINER ON) + set(ETHASHCL ON) endif () # Default CMAKE_BUILD_TYPE to "Release". @@ -283,6 +295,7 @@ message("-- FATDB Full database exploring ${FATDB}") message("-- JSONRPC JSON-RPC support ${JSONRPC}") message("-- USENPM Javascript source building ${USENPM}") message("------------------------------------------------------------- components") +message("-- MINER Build miner ${MINER}") message("-- TOOLS Build basic tools ${TOOLS}") message("-- SOLIDITY Build Solidity language components ${SOLIDITY}") message("-- SERPENT Build Serpent language components ${SERPENT}") @@ -310,10 +323,20 @@ if (EVMJIT) add_subdirectory(evmjit) endif() +if (TOOLS OR GUI OR SOLIDITY OR NCURSES OR TESTS) + set(GENERAL 1) +else () + set(GENERAL 0) +endif () + +message("GENERAL ${GENERAL}") + add_subdirectory(libdevcore) -add_subdirectory(libevmcore) -add_subdirectory(libevmasm) -add_subdirectory(liblll) +if (GENERAL) + add_subdirectory(libevmcore) + add_subdirectory(libevmasm) + add_subdirectory(liblll) +endif () if (SERPENT) add_subdirectory(libserpent) @@ -329,31 +352,43 @@ if (TOOLS) if (SOLIDITY) add_subdirectory(solc) endif () -endif() +endif () -if (JSONRPC) +if (JSONRPC AND GENERAL) add_subdirectory(libweb3jsonrpc) -endif() +endif () if (JSCONSOLE) add_subdirectory(libjsengine) add_subdirectory(libjsconsole) -endif() +endif () add_subdirectory(secp256k1) -add_subdirectory(libp2p) add_subdirectory(libdevcrypto) -add_subdirectory(libwhisper) -add_subdirectory(libethash) -if (ETHASHCL) - add_subdirectory(libethash-cl) +if (GENERAL) + add_subdirectory(libp2p) + add_subdirectory(libwhisper) +endif () + +if (GENERAL OR MINER) + add_subdirectory(libethash) + if (ETHASHCL) + add_subdirectory(libethash-cl) + endif () endif () add_subdirectory(libethcore) -add_subdirectory(libevm) -add_subdirectory(libethereum) -add_subdirectory(libwebthree) + +if (GENERAL) + add_subdirectory(libevm) + add_subdirectory(libethereum) + add_subdirectory(libwebthree) +endif () + +if (MINER) + add_subdirectory(ethminer) +endif () if (TESTS) add_subdirectory(libtestutils) @@ -367,7 +402,6 @@ if (TOOLS) add_subdirectory(rlp) add_subdirectory(abi) - add_subdirectory(ethminer) add_subdirectory(eth) if("x${CMAKE_BUILD_TYPE}" STREQUAL "xDebug") diff --git a/ethminer/CMakeLists.txt b/ethminer/CMakeLists.txt index af38c0c84..d364f6ed1 100644 --- a/ethminer/CMakeLists.txt +++ b/ethminer/CMakeLists.txt @@ -17,12 +17,7 @@ add_dependencies(${EXECUTABLE} BuildInfo.h) target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES}) -if (READLINE_FOUND) - target_link_libraries(${EXECUTABLE} ${READLINE_LIBRARIES}) -endif() - if (JSONRPC) - target_link_libraries(${EXECUTABLE} web3jsonrpc) target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_CLIENT_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${CURL_LIBRARIES}) if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) @@ -30,7 +25,7 @@ if (JSONRPC) endif() endif() -target_link_libraries(${EXECUTABLE} webthree) +target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} ethash) if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) diff --git a/ethminer/main.cpp b/ethminer/main.cpp index 10d8436f0..a19934ba0 100644 --- a/ethminer/main.cpp +++ b/ethminer/main.cpp @@ -32,12 +32,10 @@ #include #include #include +#include #include #include -#include -#include -#include -#include +#include #if ETH_JSONRPC || !ETH_TRUE #include #include @@ -50,7 +48,6 @@ #endif using namespace std; using namespace dev; -using namespace dev::p2p; using namespace dev::eth; using namespace boost::algorithm; using dev::eth::Instruction; @@ -143,7 +140,7 @@ enum class MinerType void doBenchmark(MinerType _m, bool _phoneHome, unsigned _warmupDuration = 15, unsigned _trialDuration = 3, unsigned _trials = 5) { - BlockInfo genesis = CanonBlockChain::genesis(); + BlockInfo genesis; genesis.difficulty = 1 << 18; cdebug << genesis.boundary(); @@ -294,9 +291,6 @@ void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod) int main(int argc, char** argv) { - // Init defaults - Defaults::get(); - /// Operating mode. OperationMode mode = OperationMode::Farm; diff --git a/exp/main.cpp b/exp/main.cpp index 2bd0a741e..138ae76a4 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -45,10 +45,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt index 4dd626642..a527ad1f4 100644 --- a/libethcore/CMakeLists.txt +++ b/libethcore/CMakeLists.txt @@ -28,7 +28,7 @@ add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) target_link_libraries(${EXECUTABLE} ethash) target_link_libraries(${EXECUTABLE} devcrypto) -target_link_libraries(${EXECUTABLE} evmcore) +#target_link_libraries(${EXECUTABLE} evmcore) if (ETHASHCL) target_link_libraries(${EXECUTABLE} ethash-cl) diff --git a/libethereum/Farm.h b/libethcore/Farm.h similarity index 100% rename from libethereum/Farm.h rename to libethcore/Farm.h diff --git a/libethereum/Client.h b/libethereum/Client.h index 674556a6e..7eeb7fb2d 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -37,12 +37,12 @@ #include #include #include +#include #include #include "CanonBlockChain.h" #include "TransactionQueue.h" #include "State.h" #include "CommonNet.h" -#include "Farm.h" #include "ClientBase.h" namespace dev diff --git a/libethereum/Farm.cpp b/libethereum/Farm.cpp deleted file mode 100644 index e69de29bb..000000000 From 4d2c292c7c0b73de3279772576538101de281df1 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Mon, 18 May 2015 07:35:02 +0000 Subject: [PATCH 113/157] Fixed error introduced in 953be7886b5681f0fa8ecde94b1fdb8c25afbfd4 --- test/libethereum/stateOriginal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libethereum/stateOriginal.cpp b/test/libethereum/stateOriginal.cpp index 82d6288d6..e7a078182 100644 --- a/test/libethereum/stateOriginal.cpp +++ b/test/libethereum/stateOriginal.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include "../TestHelper.h" using namespace std; From 16ce50dded9a63296dc502b3edd938f81e3ad301 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 18 May 2015 10:49:10 +0200 Subject: [PATCH 114/157] add GasMapWrapper --- mix/CodeModel.cpp | 44 ++++++++++++++++++++++++++++++++------------ mix/CodeModel.h | 27 ++++++++++++++++++++++----- 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 137188e40..e622d7973 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -333,42 +333,36 @@ void CodeModel::runCompilationJob(int _jobId) void CodeModel::gasEstimation(solidity::CompilerStack const& _cs) { - m_gasCostsMaps.clear(); + m_gasCostsMaps->deleteLater(); + m_gasCostsMaps = new GasMapWrapper(this); for (std::string n: _cs.getContractNames()) { ContractDefinition const& contractDefinition = _cs.getContractDefinition(n); QString sourceName = QString::fromStdString(*contractDefinition.getLocation().sourceName); - if (!m_gasCostsMaps.contains(sourceName)) - m_gasCostsMaps.insert(sourceName, QVariantList()); + if (!m_gasCostsMaps->contains(sourceName)) + m_gasCostsMaps->insert(sourceName, QVariantList()); if (!contractDefinition.isFullyImplemented()) continue; dev::solidity::SourceUnit const& sourceUnit = _cs.getAST(*contractDefinition.getLocation().sourceName); AssemblyItems const* items = _cs.getRuntimeAssemblyItems(n); - StructuralGasEstimator estimator; std::map gasCosts = estimator.breakToStatementLevel(estimator.performEstimation(*items, std::vector({&sourceUnit})), {&sourceUnit}); - for (auto gasItem = gasCosts.begin(); gasItem != gasCosts.end(); ++gasItem) { SourceLocation const& location = gasItem->first->getLocation(); GasMeter::GasConsumption cost = gasItem->second; std::stringstream v; v << cost.value; - GasMap* gas = new GasMap(location.start, location.end, QString::fromStdString(v.str()), cost.isInfinite); - m_gasCostsMaps.find(sourceName).value().push_back(QVariant::fromValue(gas)); + m_gasCostsMaps->push(sourceName, location.start, location.end, QString::fromStdString(v.str()), cost.isInfinite); } } } QVariantList CodeModel::gasCostByDocumentId(QString const& _documentId) const { - auto gasIter = m_gasCostsMaps.find(_documentId); - if (gasIter != m_gasCostsMaps.end()) - return gasIter.value(); - else - return QVariantList(); + return m_gasCostsMaps->gasCostsByDocId(_documentId); } void CodeModel::collectContracts(dev::solidity::CompilerStack const& _cs, std::vector const& _sourceNames) @@ -560,3 +554,29 @@ QString CodeModel::resolveFunctionName(dev::SourceLocation const& _location) } return QString(); } + +void GasMapWrapper::push(QString _source, int _start, int _end, QString _value, bool _isInfinite) +{ + GasMap* gas = new GasMap(_start, _end, _value, _isInfinite, this); + m_gasMaps.find(_source).value().push_back(QVariant::fromValue(gas)); +} + +bool GasMapWrapper::contains(QString _key) +{ + return m_gasMaps.contains(_key); +} + +void GasMapWrapper::insert(QString _source, QVariantList _variantList) +{ + m_gasMaps.insert(_source, _variantList); +} + +QVariantList GasMapWrapper::gasCostsByDocId(QString _source) +{ + auto gasIter = m_gasMaps.find(_source); + if (gasIter != m_gasMaps.end()) + return gasIter.value(); + else + return QVariantList(); +} + diff --git a/mix/CodeModel.h b/mix/CodeModel.h index 7cc9d3477..ca9658786 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -127,6 +127,26 @@ struct SourceMap LocationMap functions; }; +using SourceMaps = QMap; //by source id +using GasCostsMaps = QMap; //gas cost by contract name + +class GasMapWrapper: public QObject +{ + Q_OBJECT + + Q_PROPERTY(GasCostsMaps gasMaps MEMBER m_gasMaps CONSTANT) + +public: + GasMapWrapper(QObject* _parent): QObject(_parent){} + void push(QString _source, int _start, int _end, QString _value, bool _isInfinite); + bool contains(QString _key); + void insert(QString _source, QVariantList _variantList); + QVariantList gasCostsByDocId(QString _source); + +private: + GasCostsMaps m_gasMaps; +}; + class GasMap: public QObject { Q_OBJECT @@ -137,7 +157,7 @@ class GasMap: public QObject Q_PROPERTY(bool isInfinite MEMBER m_isInfinite CONSTANT) public: - GasMap(int _start, int _end, QString _gas, bool _isInfinite): m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } + GasMap(int _start, int _end, QString _gas, bool _isInfinite, QObject _parent): QObject(_parent), m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } int m_start; int m_end; @@ -145,9 +165,6 @@ public: bool m_isInfinite; }; -using SourceMaps = QMap; //by source id -using GasCostsMaps = QMap; //gas cost by contract name - /// Code compilation model. Compiles contracts in background an provides compiled contract data class CodeModel: public QObject { @@ -227,7 +244,7 @@ private: mutable dev::Mutex x_contractMap; ContractMap m_contractMap; SourceMaps m_sourceMaps; - GasCostsMaps m_gasCostsMaps; + GasMapWrapper* m_gasCostsMaps; std::unique_ptr m_codeHighlighterSettings; QThread m_backgroundThread; BackgroundWorker m_backgroundWorker; From 2c665ea0f9de2f8b4c4438d787b21b6f6e39be97 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 18 May 2015 11:06:34 +0200 Subject: [PATCH 115/157] small changes --- mix/CodeModel.cpp | 3 ++- mix/CodeModel.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index e622d7973..03ae828e0 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -333,7 +333,8 @@ void CodeModel::runCompilationJob(int _jobId) void CodeModel::gasEstimation(solidity::CompilerStack const& _cs) { - m_gasCostsMaps->deleteLater(); + if (m_gasCostsMaps) + m_gasCostsMaps->deleteLater(); m_gasCostsMaps = new GasMapWrapper(this); for (std::string n: _cs.getContractNames()) { diff --git a/mix/CodeModel.h b/mix/CodeModel.h index ca9658786..9295c38f0 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -244,7 +244,7 @@ private: mutable dev::Mutex x_contractMap; ContractMap m_contractMap; SourceMaps m_sourceMaps; - GasMapWrapper* m_gasCostsMaps; + GasMapWrapper* m_gasCostsMaps = 0; std::unique_ptr m_codeHighlighterSettings; QThread m_backgroundThread; BackgroundWorker m_backgroundWorker; From 9111b31ca7721feaa029c2398741a6f34a2c1361 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 18 May 2015 11:18:01 +0200 Subject: [PATCH 116/157] small changes --- mix/CodeModel.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 03ae828e0..b0edb20f9 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -363,7 +363,10 @@ void CodeModel::gasEstimation(solidity::CompilerStack const& _cs) QVariantList CodeModel::gasCostByDocumentId(QString const& _documentId) const { - return m_gasCostsMaps->gasCostsByDocId(_documentId); + if (m_gasCostsMaps) + return m_gasCostsMaps->gasCostsByDocId(_documentId); + else + return QVariantList(); } void CodeModel::collectContracts(dev::solidity::CompilerStack const& _cs, std::vector const& _sourceNames) From 8f9f7d9a6f96aef61bd7fdaf2ec027be906f97f1 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 18 May 2015 11:34:11 +0200 Subject: [PATCH 117/157] comments --- libethereum/BlockChain.cpp | 1 + libethereum/BlockQueue.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 7838e432d..f4a1dcec2 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -317,6 +317,7 @@ tuple BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st { try { + // Nonce is already verified thread at this point. auto r = import(block.first, block.second, _stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce); fresh += r.first; dead += r.second; diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index 8fa7b6cca..df134b246 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -38,6 +38,7 @@ const char* BlockQueueChannel::name() { return EthOrange "▣┅▶"; } BlockQueue::BlockQueue() { + // Allow some room for other activity unsigned verifierThreads = std::max(thread::hardware_concurrency(), 3U) - 2U; for (unsigned i = 0; i < verifierThreads; ++i) m_verifiers.emplace_back([=](){ From fff1a1379e29557907051a0f1a779bb5ab052623 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 18 May 2015 11:34:16 +0200 Subject: [PATCH 118/157] Fixed error message about explicit type conversion. --- libsolidity/AST.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 2f98ce4f6..9842901e7 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -746,7 +746,7 @@ void FunctionCall::checkTypeRequirements(TypePointers const*) //@todo for structs, we have to check the number of arguments to be equal to the // number of non-mapping members if (m_arguments.size() != 1) - BOOST_THROW_EXCEPTION(createTypeError("More than one argument for explicit type conversion.")); + BOOST_THROW_EXCEPTION(createTypeError("Exactly one argument expected for explicit type conversion.")); if (!isPositionalCall) BOOST_THROW_EXCEPTION(createTypeError("Type conversion cannot allow named arguments.")); if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type.getActualType())) From 670b4e1e7245625cc296d37d1ad328deb0158f44 Mon Sep 17 00:00:00 2001 From: winsvega Date: Wed, 6 May 2015 19:06:56 +0300 Subject: [PATCH 119/157] New Tests validBlockTestFix Solidity Contract Inheritance singletest for blockchain --- .../bcValidBlockTestFiller.json | 85 ++++++++++++++++++- .../stSolidityTestFiller.json | 6 +- 2 files changed, 84 insertions(+), 7 deletions(-) diff --git a/test/libethereum/BlockTestsFiller/bcValidBlockTestFiller.json b/test/libethereum/BlockTestsFiller/bcValidBlockTestFiller.json index dc18fb2ca..2d1bb9cfd 100644 --- a/test/libethereum/BlockTestsFiller/bcValidBlockTestFiller.json +++ b/test/libethereum/BlockTestsFiller/bcValidBlockTestFiller.json @@ -122,8 +122,8 @@ "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" }, "expect" : { - "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { - "balance" : "100" + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000" } }, "pre" : { @@ -139,8 +139,8 @@ "transactions" : [ { "data" : "", - "gasLimit" : "100001", - "gasPrice" : "0", + "gasLimit" : "10000001", + "gasPrice" : "1", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", @@ -153,6 +153,83 @@ ] }, + "gasLimitTooHigh2" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "131072", + "extraData" : "0x42", + "gasLimit" : "3141592", + "gasUsed" : "0", + "mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0x0102030405060708", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "30" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "1", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "1", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "21000", + "gasPrice" : "1", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + } + ] + }, + "SimpleTx" : { "genesisBlockHeader" : { "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", diff --git a/test/libethereum/StateTestsFiller/stSolidityTestFiller.json b/test/libethereum/StateTestsFiller/stSolidityTestFiller.json index a4243c8dd..7ee5db0c3 100644 --- a/test/libethereum/StateTestsFiller/stSolidityTestFiller.json +++ b/test/libethereum/StateTestsFiller/stSolidityTestFiller.json @@ -47,16 +47,16 @@ "//" : " function testInheretance() returns (bool res) ", "//" : " { ", "//" : " res = true; ", - "//" : " base contract1; ", + "//" : " base contract1 = new base(); ", "//" : " if (contract1.methodA() != 1) ", "//" : " return false; ", "//" : " ", - "//" : " frombase contract2; ", + "//" : " frombase contract2 = new frombase(); ", "//" : " if (contract2.methodA() != 2) ", "//" : " return false; ", "//" : " } ", "//" : "} ", - "code" : "0x6000357c0100000000000000000000000000000000000000000000000000000000900480633e0bca3b1461003a578063c04062261461004c57005b610042610099565b8060005260206000f35b61005461005e565b8060005260206000f35b6000610068610099565b600060006101000a81548160ff02191690830217905550600060009054906101000a900460ff169050610096565b90565b60006000600060019250825060018273ffffffffffffffffffffffffffffffffffffffff166381bda09b60206000827c010000000000000000000000000000000000000000000000000000000002600052600460006000866161da5a03f16100fd57005b505060005163ffffffff1614156101135761011c565b60009250610194565b60028173ffffffffffffffffffffffffffffffffffffffff166381bda09b60206000827c010000000000000000000000000000000000000000000000000000000002600052600460006000866161da5a03f161017457005b505060005163ffffffff16141561018a57610193565b60009250610194565b5b50509056", + "code" : "0x7c010000000000000000000000000000000000000000000000000000000060003504633e0bca3b8114610039578063c0406226146100a857005b6100b55b600160008060456101ec8339604560006000f091508173ffffffffffffffffffffffffffffffffffffffff166381bda09b60206000827c010000000000000000000000000000000000000000000000000000000002600052600460006000866161da5a03f161011957005b6100bf60006100c961003d565b8060005260206000f35b8060005260206000f35b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016919091179081905560ff16919050565b505060005163ffffffff166002141561019d575b5b505090565b505060005163ffffffff1660011415610194575b60456101a7600039604560006000f090508073ffffffffffffffffffffffffffffffffffffffff166381bda09b60206000827c010000000000000000000000000000000000000000000000000000000002600052600460006000866161da5a03f16100ff57005b60009250610114565b600092506101145600603980600c6000396000f3007c0100000000000000000000000000000000000000000000000000000000600035046381bda09b8114602d57005b60026000818152602090f3603980600c6000396000f3007c0100000000000000000000000000000000000000000000000000000000600035046381bda09b8114602d57005b60016000818152602090f3", "nonce" : "0", "storage" : { } From 55186b689a94d771ae75b3a5ba6cfd4c9e8cb3a4 Mon Sep 17 00:00:00 2001 From: winsvega Date: Mon, 18 May 2015 13:32:26 +0300 Subject: [PATCH 120/157] Blocktests: SimpleTx3 --- .../bcValidBlockTestFiller.json | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/test/libethereum/BlockTestsFiller/bcValidBlockTestFiller.json b/test/libethereum/BlockTestsFiller/bcValidBlockTestFiller.json index 2d1bb9cfd..2dbbb5032 100644 --- a/test/libethereum/BlockTestsFiller/bcValidBlockTestFiller.json +++ b/test/libethereum/BlockTestsFiller/bcValidBlockTestFiller.json @@ -280,6 +280,96 @@ ] }, + "SimpleTx3" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "131072", + "extraData" : "0x42", + "gasLimit" : "3141592", + "gasUsed" : "0", + "mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0x0102030405060708", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "expect" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "10" + }, + "000000000000000000000000000b9331677e6ebf" : { + "balance" : "10" + }, + "b94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10" + } + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "31bb58672e8bf7684108feeacf424ab62b873824" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "fa7f04899691becd07dd3081d0a2f3ee7640af52" : { + "balance" : "10000000000", + "nonce" : "3", + "code" : "", + "storage": {} + } + }, + "blocks" : [ + { + "transactions" : [ + { + "data" : "", + "gasLimit" : "50000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + }, + { + "data" : "", + "gasLimit" : "0x5208", + "gasPrice" : "0x01", + "nonce" : "0x00", + "r" : "0x98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a", + "s" : "0x8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3", + "to" : "000000000000000000000000000b9331677e6ebf", + "v" : "0x1c", + "value" : "0x0a" + }, + { + "data" : "0x", + "gasLimit" : "0x5208", + "gasPrice" : "0x01", + "nonce" : "0x03", + "r" : "0x98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a", + "s" : "0x8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3", + "to" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "v" : "0x1c", + "value" : "0x0a" + } + ], + "uncleHeaders" : [ + ] + } + ] + }, + "txOrder" : { "genesisBlockHeader" : { "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", From a6f80e6f973f249f61d565e3c3c0a37918bb7cfb Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 18 May 2015 12:42:21 +0200 Subject: [PATCH 121/157] Use straight homedirectory rather than Application Support. --- libethcore/EthashAux.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index 59155610f..2c96c3ff0 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -181,10 +181,18 @@ EthashAux::FullType EthashAux::full(h256 const& _seedHash, bool _createIfMissing return ret; } +#define DEV_IF_THROWS(X) try { X; } catch (...) + unsigned EthashAux::computeFull(h256 const& _seedHash) { Guard l(get()->x_fulls); - uint64_t blockNumber = EthashAux::number(_seedHash); + uint64_t blockNumber; + + DEV_IF_THROWS(blockNumber = EthashAux::number(_seedHash)) + { + return 0; + } + if (FullType ret = get()->m_fulls[_seedHash].lock()) { get()->m_lastUsedFull = ret; @@ -232,5 +240,8 @@ Ethash::Result EthashAux::eval(h256 const& _seedHash, h256 const& _headerHash, N { if (FullType dag = get()->m_fulls[_seedHash].lock()) return dag->compute(_headerHash, _nonce); - return EthashAux::get()->light(_seedHash)->compute(_headerHash, _nonce); + DEV_IF_THROWS(return EthashAux::get()->light(_seedHash)->compute(_headerHash, _nonce)) + { + return Ethash::Result(~h256(), h256()); + } } From fea144622a5e017446ab1660f426dead40647452 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 18 May 2015 13:16:46 +0200 Subject: [PATCH 122/157] Bump and build fix. --- libdevcore/Common.cpp | 2 +- libdevcrypto/FileSystem.cpp | 5 ----- libethcore/Ethash.h | 1 - libethcore/EthashAux.cpp | 2 +- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 7171c4a2b..cb9b94de8 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -28,7 +28,7 @@ using namespace dev; namespace dev { -char const* Version = "0.9.22"; +char const* Version = "0.9.23"; const u256 UndefinedU256 = ~(u256)0; diff --git a/libdevcrypto/FileSystem.cpp b/libdevcrypto/FileSystem.cpp index e3b8c6e3f..adf3a2946 100644 --- a/libdevcrypto/FileSystem.cpp +++ b/libdevcrypto/FileSystem.cpp @@ -70,11 +70,6 @@ std::string dev::getDataDir(std::string _prefix) else dataDirPath = boost::filesystem::path(homeDir); -#if defined(__APPLE__) && defined(__MACH__) - // This eventually needs to be put in proper wrapper (to support sandboxing) - return (dataDirPath / "Library/Application Support/Ethereum").string(); -#else return (dataDirPath / ("." + _prefix)).string(); #endif -#endif } diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 0fd2e4cd0..81f842e4f 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -79,7 +79,6 @@ public: static WorkPackage package(BlockInfo const& _header); static void assignResult(Solution const& _r, BlockInfo& _header) { _header.nonce = _r.nonce; _header.mixHash = _r.mixHash; } - class CPUMiner: public Miner, Worker { public: diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index 2c96c3ff0..805585b4f 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -242,6 +242,6 @@ Ethash::Result EthashAux::eval(h256 const& _seedHash, h256 const& _headerHash, N return dag->compute(_headerHash, _nonce); DEV_IF_THROWS(return EthashAux::get()->light(_seedHash)->compute(_headerHash, _nonce)) { - return Ethash::Result(~h256(), h256()); + return Ethash::Result{ ~h256(), h256() }; } } From 09f13ce1a6a50cc8929212e194434789f7f1768a Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 18 May 2015 14:39:07 +0200 Subject: [PATCH 123/157] small change --- mix/CodeModel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix/CodeModel.h b/mix/CodeModel.h index 9295c38f0..95c44febe 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -157,7 +157,7 @@ class GasMap: public QObject Q_PROPERTY(bool isInfinite MEMBER m_isInfinite CONSTANT) public: - GasMap(int _start, int _end, QString _gas, bool _isInfinite, QObject _parent): QObject(_parent), m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } + GasMap(int _start, int _end, QString _gas, bool _isInfinite, QObject* _parent): QObject(_parent), m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } int m_start; int m_end; From 5d759f549b770455d8c1668b03c82b145897d65b Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 18 May 2015 15:14:48 +0200 Subject: [PATCH 124/157] mix bugfixes --- mix/ClientModel.cpp | 151 ++++++++++++------------------- mix/qml.qrc | 1 - mix/qml/ContractLibrary.qml | 27 ------ mix/qml/StateListModel.qml | 29 +----- mix/qml/TransactionDialog.qml | 2 + mix/qml/html/cm/codemirror.css | 4 + mix/qml/html/cm/solidityToken.js | 2 +- 7 files changed, 68 insertions(+), 148 deletions(-) delete mode 100644 mix/qml/ContractLibrary.qml diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 7638db635..54d5db2b5 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -256,32 +256,17 @@ void ClientModel::setupState(QVariantMap _state) u256 value = (qvariant_cast(transaction.value("value")))->toU256Wei(); u256 gasPrice = (qvariant_cast(transaction.value("gasPrice")))->toU256Wei(); QString sender = transaction.value("sender").toString(); - bool isStdContract = transaction.value("stdContract").toBool(); bool isContractCreation = transaction.value("isContractCreation").toBool(); bool isFunctionCall = transaction.value("isFunctionCall").toBool(); - if (isStdContract) - { - if (contractId.isEmpty()) //TODO: This is to support old project files, remove later - contractId = functionId; - TransactionSettings transactionSettings(contractId, transaction.value("url").toString()); - transactionSettings.gasPrice = 10000000000000; - transactionSettings.gasAuto = true; - transactionSettings.value = 0; - transactionSettings.sender = Secret(sender.toStdString()); - transactionSequence.push_back(transactionSettings); - } - else - { - if (contractId.isEmpty() && m_codeModel->hasContract()) //TODO: This is to support old project files, remove later - contractId = m_codeModel->contracts().keys()[0]; - TransactionSettings transactionSettings(contractId, functionId, value, gas, gasAuto, gasPrice, Secret(sender.toStdString()), isContractCreation, isFunctionCall); - transactionSettings.parameterValues = transaction.value("parameters").toMap(); + if (contractId.isEmpty() && m_codeModel->hasContract()) //TODO: This is to support old project files, remove later + contractId = m_codeModel->contracts().keys()[0]; + TransactionSettings transactionSettings(contractId, functionId, value, gas, gasAuto, gasPrice, Secret(sender.toStdString()), isContractCreation, isFunctionCall); + transactionSettings.parameterValues = transaction.value("parameters").toMap(); - if (contractId == functionId || functionId == "Constructor") - transactionSettings.functionId.clear(); + if (contractId == functionId || functionId == "Constructor") + transactionSettings.functionId.clear(); - transactionSequence.push_back(transactionSettings); - } + transactionSequence.push_back(transactionSettings); } m_ethAccounts->setAccounts(userAccounts); executeSequence(transactionSequence, accounts, Secret(_state.value("miner").toMap().value("secret").toString().toStdString())); @@ -319,79 +304,66 @@ void ClientModel::executeSequence(vector const& _sequence, continue; } ContractCallDataEncoder encoder; - if (!transaction.stdContractUrl.isEmpty()) + //encode data + CompiledContract const& compilerRes = m_codeModel->contract(ctrInstance.first); + QFunctionDefinition const* f = nullptr; + bytes contractCode = compilerRes.bytes(); + shared_ptr contractDef = compilerRes.sharedContract(); + if (transaction.functionId.isEmpty()) + f = contractDef->constructor(); + else + for (QFunctionDefinition const* tf: contractDef->functionsList()) + if (tf->name() == transaction.functionId) + { + f = tf; + break; + } + if (!f) { - //std contract - bytes const& stdContractCode = m_codeModel->getStdContractCode(transaction.contractId, transaction.stdContractUrl); - TransactionSettings stdTransaction = transaction; - stdTransaction.gasAuto = true; - Address address = deployContract(stdContractCode, stdTransaction); - m_stdContractAddresses[stdTransaction.contractId] = address; - m_stdContractNames[address] = stdTransaction.contractId; + emit runFailed("Function '" + transaction.functionId + tr("' not found. Please check transactions or the contract code.")); + m_running = false; + emit runStateChanged(); + return; + } + if (!transaction.functionId.isEmpty()) + encoder.encode(f); + for (QVariableDeclaration const* p: f->parametersList()) + { + QSolidityType const* type = p->type(); + QVariant value = transaction.parameterValues.value(p->name()); + if (type->type().type == SolidityType::Type::Address) + { + std::pair ctrParamInstance = resolvePair(value.toString()); + value = QVariant(resolveToken(ctrParamInstance, deployedContracts)); + } + encoder.encode(value, type->type()); + } + + if (transaction.functionId.isEmpty() || transaction.functionId == ctrInstance.first) + { + bytes param = encoder.encodedData(); + contractCode.insert(contractCode.end(), param.begin(), param.end()); + Address newAddress = deployContract(contractCode, transaction); + deployedContracts.push_back(newAddress); + std::pair contractToken = retrieveToken(transaction.contractId, deployedContracts); + m_contractAddresses[contractToken] = newAddress; + m_contractNames[newAddress] = contractToken.first; + contractAddressesChanged(); + gasCostsChanged(); } else { - //encode data - CompiledContract const& compilerRes = m_codeModel->contract(ctrInstance.first); - QFunctionDefinition const* f = nullptr; - bytes contractCode = compilerRes.bytes(); - shared_ptr contractDef = compilerRes.sharedContract(); - if (transaction.functionId.isEmpty()) - f = contractDef->constructor(); - else - for (QFunctionDefinition const* tf: contractDef->functionsList()) - if (tf->name() == transaction.functionId) - { - f = tf; - break; - } - if (!f) + auto contractAddressIter = m_contractAddresses.find(ctrInstance); + if (contractAddressIter == m_contractAddresses.end()) { - emit runFailed("Function '" + transaction.functionId + tr("' not found. Please check transactions or the contract code.")); + emit runFailed("Contract '" + transaction.contractId + tr(" not deployed.") + "' " + tr(" Cannot call ") + transaction.functionId); m_running = false; emit runStateChanged(); return; } - if (!transaction.functionId.isEmpty()) - encoder.encode(f); - for (QVariableDeclaration const* p: f->parametersList()) - { - QSolidityType const* type = p->type(); - QVariant value = transaction.parameterValues.value(p->name()); - if (type->type().type == SolidityType::Type::Address) - { - std::pair ctrParamInstance = resolvePair(value.toString()); - value = QVariant(resolveToken(ctrParamInstance, deployedContracts)); - } - encoder.encode(value, type->type()); - } - - if (transaction.functionId.isEmpty() || transaction.functionId == ctrInstance.first) - { - bytes param = encoder.encodedData(); - contractCode.insert(contractCode.end(), param.begin(), param.end()); - Address newAddress = deployContract(contractCode, transaction); - deployedContracts.push_back(newAddress); - std::pair contractToken = retrieveToken(transaction.contractId, deployedContracts); - m_contractAddresses[contractToken] = newAddress; - m_contractNames[newAddress] = contractToken.first; - contractAddressesChanged(); - gasCostsChanged(); - } - else - { - auto contractAddressIter = m_contractAddresses.find(ctrInstance); - if (contractAddressIter == m_contractAddresses.end()) - { - emit runFailed("Contract '" + transaction.contractId + tr(" not deployed.") + "' " + tr(" Cannot call ") + transaction.functionId); - m_running = false; - emit runStateChanged(); - return; - } - callAddress(contractAddressIter->second, encoder.encodedData(), transaction); - } - m_gasCosts.append(m_client->lastExecution().gasUsed); + callAddress(contractAddressIter->second, encoder.encodedData(), transaction); } + m_gasCosts.append(m_client->lastExecution().gasUsed); onNewTransaction(); } m_running = false; @@ -697,14 +669,7 @@ void ClientModel::onNewTransaction() if (creation) { //contract creation - auto const stdContractName = m_stdContractNames.find(tr.contractAddress); - if (stdContractName != m_stdContractNames.end()) - { - function = stdContractName->second; - contract = function; - } - else - function = QObject::tr("Constructor"); + function = QObject::tr("Constructor"); address = QObject::tr("(Create contract)"); } else diff --git a/mix/qml.qrc b/mix/qml.qrc index 6cbc97a78..c47a7254f 100644 --- a/mix/qml.qrc +++ b/mix/qml.qrc @@ -8,7 +8,6 @@ qml/CodeEditorStyle.qml qml/CodeEditorView.qml qml/CommonSeparator.qml - qml/ContractLibrary.qml qml/DebugBasicInfo.qml qml/DebugInfoList.qml qml/Debugger.qml diff --git a/mix/qml/ContractLibrary.qml b/mix/qml/ContractLibrary.qml deleted file mode 100644 index 4f3afafc6..000000000 --- a/mix/qml/ContractLibrary.qml +++ /dev/null @@ -1,27 +0,0 @@ -import QtQuick 2.2 - -Item { - id: contractLibrary - property alias model: contractListModel; - - Connections { - target: mainApplication - onLoaded: { - - //TODO: load a list, dependencies, ets, from external files - contractListModel.append({ - name: "Config", - url: "qrc:///stdc/std.sol", - }); - contractListModel.append({ - name: "NameReg", - url: "qrc:///stdc/std.sol", - }); - } - } - - ListModel { - id: contractListModel - } -} - diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index b4d9b6bc6..f21c93199 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -22,7 +22,7 @@ Item { s.contracts = []; return { title: s.title, - transactions: s.transactions.map(fromPlainTransactionItem), + transactions: s.transactions.filter(function(t) { return !t.stdContract; }).map(fromPlainTransactionItem), //support old projects by filtering std contracts accounts: s.accounts.map(fromPlainAccountItem), contracts: s.contracts.map(fromPlainAccountItem), miner: s.miner @@ -54,7 +54,6 @@ Item { gas: QEtherHelper.createBigInt(t.gas.value), gasPrice: QEtherHelper.createEther(t.gasPrice.value, t.gasPrice.unit), gasAuto: t.gasAuto, - stdContract: t.stdContract ? true : false, parameters: {}, sender: t.sender, isContractCreation: t.isContractCreation, @@ -122,7 +121,6 @@ Item { gas: { value: t.gas.value() }, gasAuto: t.gasAuto, gasPrice: { value: t.gasPrice.value, unit: t.gasPrice.unit }, - stdContract: t.stdContract, sender: t.sender, parameters: {}, isContractCreation: t.isContractCreation, @@ -189,10 +187,6 @@ Item { } } - ContractLibrary { - id: contractLibrary; - } - ListModel { id: stateListModel property int defaultStateIndex: 0 @@ -226,18 +220,6 @@ Item { item.accounts.push(account); item.miner = account; - //add all stdc contracts - for (var i = 0; i < contractLibrary.model.count; i++) { - var contractTransaction = defaultTransactionItem(); - var contractItem = contractLibrary.model.get(i); - contractTransaction.url = contractItem.url; - contractTransaction.contractId = contractItem.name; - contractTransaction.functionId = contractItem.name; - contractTransaction.stdContract = true; - contractTransaction.sender = item.accounts[0].secret; // default account is used to deploy std contract. - item.transactions.push(contractTransaction); - }; - //add constructors, //TODO: order by dependencies for(var c in codeModel.contracts) { var ctorTr = defaultTransactionItem(); @@ -273,17 +255,12 @@ Item { } function addNewContracts() { - //add new contracts for all states + //add new contracts to empty states var changed = false; for (var c in codeModel.contracts) { for (var s = 0; s < stateListModel.count; s++) { var state = stateList[s]; - for (var t = 0; t < state.transactions.length; t++) { - var transaction = state.transactions[t]; - if (transaction.functionId === c && transaction.contractId === c) - break; - } - if (t === state.transactions.length) { + if (state.transactions.length === 0) { //append this contract var ctorTr = defaultTransactionItem(); ctorTr.functionId = c; diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index fe4bfc82e..1437c2562 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -210,6 +210,8 @@ Dialog { } item.isContractCreation = trType.checked; + if (item.isContractCreation) + item.functionId = item.contractId; item.isFunctionCall = item.functionId !== " - "; if (!item.isContractCreation) diff --git a/mix/qml/html/cm/codemirror.css b/mix/qml/html/cm/codemirror.css index 625baa942..c25a3ddad 100644 --- a/mix/qml/html/cm/codemirror.css +++ b/mix/qml/html/cm/codemirror.css @@ -8,6 +8,10 @@ font-size:12px } +.CodeMirror-search-field { + height:200%; +} + /* BREAKPOINTS */ .breakpoints {width: .8em;} .breakpoint { color: #822; } diff --git a/mix/qml/html/cm/solidityToken.js b/mix/qml/html/cm/solidityToken.js index d8e588a10..1c12278e1 100644 --- a/mix/qml/html/cm/solidityToken.js +++ b/mix/qml/html/cm/solidityToken.js @@ -5,7 +5,7 @@ function solCurrency() function solKeywords() { - return { "break": true, "case": true, "constant": true, "continue": true, "contract": true, "default": true, "do": true, "else": true, "event": true, "external": true, "is": true, "indexed": true, "for": true, "function": true, "if": true, "import": true, "mapping": true, "modifier": true, "new": true, "public": true, "private": true, "internal": true, "return": true, "returns": true, "struct": true, "switch": true, "var": true, "while": true, "enum": true }; + return { "break": true, "case": true, "constant": true, "continue": true, "contract": true, "default": true, "delete": true, "do": true, "else": true, "event": true, "external": true, "is": true, "indexed": true, "for": true, "function": true, "if": true, "import": true, "mapping": true, "modifier": true, "new": true, "public": true, "private": true, "internal": true, "return": true, "returns": true, "struct": true, "switch": true, "var": true, "while": true, "enum": true }; } function solStdContract() From db12fc1d83c534e68c83daceb5ee46f236b0594e Mon Sep 17 00:00:00 2001 From: subtly Date: Mon, 18 May 2015 15:28:19 +0200 Subject: [PATCH 125/157] Don't abort connecting to required peer when it's not in node table. --- libp2p/Host.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 9c3e629d4..e2599c1d5 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -475,9 +475,11 @@ void Host::connect(std::shared_ptr const& _p) if (!!m_nodeTable && !m_nodeTable->haveNode(_p->id)) { - clog(NetWarn) << "Aborted connect. Node not in node table."; + // connect was attempted, so try again by adding to node table m_nodeTable->addNode(*_p.get()); - return; + // abort unless peer is required + if (!_p->required) + return; } // prevent concurrently connecting to a node From 66c2e4b4598a3160f95d9dc09a4b14faa2a2bf4a Mon Sep 17 00:00:00 2001 From: subtly Date: Mon, 18 May 2015 15:56:45 +0200 Subject: [PATCH 126/157] normalize path for osx --- libethash/io_posix.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libethash/io_posix.c b/libethash/io_posix.c index b030748a9..1fe82973f 100644 --- a/libethash/io_posix.c +++ b/libethash/io_posix.c @@ -90,20 +90,16 @@ bool ethash_file_size(FILE* f, size_t* ret_size) bool ethash_get_default_dirname(char* strbuf, size_t buffsize) { -#if defined(__APPLE__) - static const char dir_suffix[] = "Ethash/"; + static const char dir_suffix[] = ".ethash/"; strbuf[0] = '\0'; char* home_dir = getenv("HOME"); +#if defined(__APPLE__) if (!home_dir || strlen(home_dir) == 0) { struct passwd* pwd = getpwuid(getuid()); if (pwd) home_dir = pwd->pw_dir; } -#else - static const char dir_suffix[] = ".ethash/"; - strbuf[0] = '\0'; - char* home_dir = getenv("HOME"); #endif size_t len = strlen(home_dir); From 4e4f899745e190d5b8507488c0e7a2491ad8e6d9 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Mon, 18 May 2015 16:29:26 +0200 Subject: [PATCH 127/157] add create retrun value tests --- .../stCallCreateCallCodeTestFiller.json | 238 ++++++++++++++++++ .../stRecursiveCreateFiller.json | 36 ++- 2 files changed, 273 insertions(+), 1 deletion(-) diff --git a/test/libethereum/StateTestsFiller/stCallCreateCallCodeTestFiller.json b/test/libethereum/StateTestsFiller/stCallCreateCallCodeTestFiller.json index d75439f78..682b0cb3e 100644 --- a/test/libethereum/StateTestsFiller/stCallCreateCallCodeTestFiller.json +++ b/test/libethereum/StateTestsFiller/stCallCreateCallCodeTestFiller.json @@ -787,5 +787,243 @@ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data" : "0x60406103ca600439600451602451336000819055506000600481905550816001819055508060028190555042600581905550336003819055505050610381806100496000396000f30060003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b505600000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000023" } + }, + + "createInitFailStackUnderflow": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "100000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{(MSTORE8 0 0x01 ) (SUICIDE (CREATE 1 0 1)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "100000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "createInitFailUndefinedInstruction": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "100000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{(MSTORE8 0 0xf4 ) (SUICIDE (CREATE 1 0 1)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "100000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "createInitFailBadJumpDestination": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "100000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{(MSTORE8 0 0x56 ) (SUICIDE (CREATE 1 0 1)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "100000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "createInitFail_OOGduringInit": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "100000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{(MSTORE8 0 0x5a ) (SUICIDE (CREATE 1 0 1)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "53021", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "createInitFailStackSizeLargerThan1024": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "100000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{(MSTORE 0 0x6103ff6000525b7f0102030405060708090a0102030405060708090a01020304) (MSTORE 32 0x05060708090a0102600160005103600052600051600657000000000000000000 ) (SUICIDE (CREATE 1 0 64)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "100000000", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "createFailBalanceTooLow": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "100000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{(MSTORE8 0 0x5a ) (SUICIDE (CREATE 1000000000000000024 0 1)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "53021", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "23", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } + }, + + "createInitOOGforCREATE": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "100000000", + "currentDifficulty" : "256", + "currentTimestamp" : 1, + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "{(MSTORE8 0 0x5a ) (SUICIDE (CREATE 1 0 1)) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transaction" : { + "nonce" : "0", + "gasPrice" : "1", + "gasLimit" : "53020", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "100000", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data" : "" + } } } diff --git a/test/libethereum/StateTestsFiller/stRecursiveCreateFiller.json b/test/libethereum/StateTestsFiller/stRecursiveCreateFiller.json index 25a909d9c..acaccbeb2 100644 --- a/test/libethereum/StateTestsFiller/stRecursiveCreateFiller.json +++ b/test/libethereum/StateTestsFiller/stRecursiveCreateFiller.json @@ -31,5 +31,39 @@ "secretKey": "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "data": "" } - } + }, + + "recursiveCreateReturnValue": { + "env": { + "previousHash": "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber": "0", + "currentGasLimit": "10000000000", + "currentDifficulty": "256", + "currentTimestamp": 1, + "currentCoinbase": "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre": { + "095e7baea6a6c7c4c2dfeb977efac326af552d87": { + "balance": "20000000", + "nonce" : "0", + "code": "{(CODECOPY 0 0 32) [[ 0 ]] (ADD (CREATE 0 0 32) 1) }", + "storage": {} + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "1000000000000000000", + "nonce" : "0", + "code": "", + "storage": {} + } + }, + "transaction": { + "nonce": "0", + "gasPrice": "1", + "gasLimit": "1000000000", + "to": "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value": "100000", + "secretKey": "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "data": "" + } + } } From 6879c04393658f382ecd441947831c3a08e0830d Mon Sep 17 00:00:00 2001 From: subtly Date: Mon, 18 May 2015 16:54:32 +0200 Subject: [PATCH 128/157] Update paths so macos is consistent with linux and windows isn't using wchar. --- io_posix.c | 13 +++++++++++++ io_win32.c | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/io_posix.c b/io_posix.c index 7f03d5482..1fe82973f 100644 --- a/io_posix.c +++ b/io_posix.c @@ -26,6 +26,10 @@ #include #include #include +#if defined(__APPLE__) +#include +#include +#endif FILE* ethash_fopen(char const* file_name, char const* mode) { @@ -89,6 +93,15 @@ bool ethash_get_default_dirname(char* strbuf, size_t buffsize) static const char dir_suffix[] = ".ethash/"; strbuf[0] = '\0'; char* home_dir = getenv("HOME"); +#if defined(__APPLE__) + if (!home_dir || strlen(home_dir) == 0) + { + struct passwd* pwd = getpwuid(getuid()); + if (pwd) + home_dir = pwd->pw_dir; + } +#endif + size_t len = strlen(home_dir); if (!ethash_strncat(strbuf, buffsize, home_dir, len)) { return false; diff --git a/io_win32.c b/io_win32.c index 2e6c8deb8..34f1aaa77 100644 --- a/io_win32.c +++ b/io_win32.c @@ -87,9 +87,9 @@ bool ethash_file_size(FILE* f, size_t* ret_size) bool ethash_get_default_dirname(char* strbuf, size_t buffsize) { - static const char dir_suffix[] = "Appdata\\Ethash\\"; + static const char dir_suffix[] = "Ethash\\"; strbuf[0] = '\0'; - if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, (WCHAR*)strbuf))) { + if (!SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, (CHAR*)strbuf))) { return false; } if (!ethash_strncat(strbuf, buffsize, "\\", 1)) { From aa43d7261d5433a231f9d36abea074ce95f8c811 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Mon, 18 May 2015 16:59:35 +0200 Subject: [PATCH 129/157] fix Create return value for exceptional haltings --- libethereum/Executive.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 2d8dbdc16..a1eee9440 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -246,6 +246,9 @@ bool Executive::go(OnOpFunc const& _onOp) m_endGas = 0; m_excepted = toTransactionException(_e); m_ext->revert(); + + if (m_isCreation) + m_newAddress = Address(); } catch (Exception const& _e) { From 53d63f80c3eb42eab38e3a0e9d58b7dd304efea1 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 18 May 2015 17:15:30 +0200 Subject: [PATCH 130/157] Pull out shared code into Aux file. --- alethzero/MainWin.cpp | 3 + eth/main.cpp | 549 ++++------------------------------------- ethminer/MinerAux.h | 483 ++++++++++++++++++++++++++++++++++++ ethminer/main.cpp | 429 +------------------------------- libethcore/Ethash.cpp | 4 +- libethcore/EthashAux.h | 2 + 6 files changed, 550 insertions(+), 920 deletions(-) create mode 100644 ethminer/MinerAux.h diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 191db6eb4..9486f9f01 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1166,6 +1166,9 @@ void Main::on_turboMining_triggered() void Main::refreshBlockChain() { + if (!ui->blocks->isVisible()) + return; + DEV_TIMED_FUNCTION; cwatch << "refreshBlockChain()"; diff --git a/eth/main.cpp b/eth/main.cpp index 5f2349ae4..1cf918346 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -57,6 +57,7 @@ #include "PhoneHome.h" #include "Farm.h" #endif +#include using namespace std; using namespace dev; using namespace dev::p2p; @@ -64,18 +65,6 @@ using namespace dev::eth; using namespace boost::algorithm; using dev::eth::Instruction; -#undef RETURN - -bool isTrue(std::string const& _m) -{ - return _m == "on" || _m == "yes" || _m == "true" || _m == "1"; -} - -bool isFalse(std::string const& _m) -{ - return _m == "off" || _m == "no" || _m == "false" || _m == "0"; -} - void interactiveHelp() { cout @@ -159,33 +148,13 @@ void help() << " --port Connect to remote port (default: 30303)." << endl << " --network-id Only connect to other hosts with this network id (default:0)." << endl << " --upnp Use UPnP for NAT (default: on)." << endl - << endl + << endl; + MinerCLI::streamHelp(cout); + cout << "Client structured logging:" << endl << " --structured-logging Enable structured logging (default output to stdout)." << endl << " --structured-logging-format Set the structured logging time format." << endl << " --structured-logging-url Set the structured logging destination (currently only file:// supported)." << 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 - << " --benchmark-trial Set the duration for each trial for the benchmark tests (default: 3)." << endl - << " --benchmark-trials Set the duration of warmup for the benchmark tests (default: 5)." << endl -#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 @@ -208,20 +177,13 @@ void help() exit(0); } -string credits(bool _interactive = false) +string ethCredits(bool _interactive = false) { std::ostringstream cout; - cout - << "Ethereum (++) " << dev::Version << endl - << " Code by Gav Wood et al, (c) 2013, 2014, 2015." << endl - << " Based on a design by Vitalik Buterin." << endl << endl; - if (_interactive) cout - << "Type 'netstart 30303' to start networking" << endl - << "Type 'connect " << Host::pocHost() << " 30303' to connect" << endl << "Type 'exit' to quit" << endl << endl; - return cout.str(); + return credits() + cout.str(); } void version() @@ -263,23 +225,11 @@ enum class NodeMode Full }; -void doInitDAG(unsigned _n) -{ - BlockInfo bi; - bi.number = _n; - cout << "Initializing DAG for epoch beginning #" << (bi.number / 30000 * 30000) << " (seedhash " << bi.seedHash().abridged() << "). This will take a while." << endl; - Ethash::prep(bi); - exit(0); -} - enum class OperationMode { Node, Import, - Export, - DAGInit, - Benchmark, - Farm + Export }; enum class Format @@ -289,148 +239,6 @@ enum class Format Human }; -enum class MinerType -{ - CPU, - GPU -}; - -void doBenchmark(MinerType _m, bool _phoneHome, unsigned _warmupDuration = 15, unsigned _trialDuration = 3, unsigned _trials = 5) -{ - BlockInfo genesis = CanonBlockChain::genesis(); - genesis.difficulty = 1 << 18; - cdebug << genesis.boundary(); - - GenericFarm f; - f.onSolutionFound([&](ProofOfWork::Solution) { return false; }); - - string platformInfo = _m == MinerType::CPU ? ProofOfWork::CPUMiner::platformInfo() : _m == MinerType::GPU ? ProofOfWork::GPUMiner::platformInfo() : ""; - cout << "Benchmarking on platform: " << platformInfo << endl; - - cout << "Preparing DAG..." << endl; - Ethash::prep(genesis); - - genesis.difficulty = u256(1) << 63; - genesis.noteDirty(); - f.setWork(genesis); - if (_m == MinerType::CPU) - f.startCPU(); - else if (_m == MinerType::GPU) - f.startGPU(); - - map results; - uint64_t mean = 0; - uint64_t innerMean = 0; - for (unsigned i = 0; i <= _trials; ++i) - { - if (!i) - cout << "Warming up..." << endl; - else - cout << "Trial " << i << "... " << flush; - this_thread::sleep_for(chrono::seconds(i ? _trialDuration : _warmupDuration)); - - auto mp = f.miningProgress(); - f.resetMiningProgress(); - if (!i) - continue; - auto rate = mp.rate(); - - cout << rate << endl; - results[rate] = mp; - mean += rate; - if (i > 1 && i < 5) - innerMean += rate; - } - f.stop(); - innerMean /= (_trials - 2); - cout << "min/mean/max: " << results.begin()->second.rate() << "/" << (mean / _trials) << "/" << results.rbegin()->second.rate() << " H/s" << endl; - cout << "inner mean: " << innerMean << " H/s" << endl; - - (void)_phoneHome; -#if ETH_JSONRPC || !ETH_TRUE - if (_phoneHome) - { - cout << "Phoning home to find world ranking..." << endl; - jsonrpc::HttpClient client("http://gav.ethdev.com:3000/benchmark"); - PhoneHome rpc(client); - try - { - unsigned ranking = rpc.report_benchmark(platformInfo, innerMean); - cout << "Ranked: " << ranking << " of all benchmarks." << endl; - } - catch (...) - { - cout << "Error phoning home. ET is sad." << endl; - } - } -#endif - exit(0); -} - -struct HappyChannel: public LogChannel { static const char* name() { return ":-D"; } static const int verbosity = 1; }; -struct SadChannel: public LogChannel { static const char* name() { return ":-("; } static const int verbosity = 1; }; - -void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod) -{ - (void)_m; - (void)_remote; - (void)_recheckPeriod; -#if ETH_JSONRPC || !ETH_TRUE - jsonrpc::HttpClient client(_remote); - Farm rpc(client); - GenericFarm f; - if (_m == MinerType::CPU) - f.startCPU(); - else if (_m == MinerType::GPU) - f.startGPU(); - - ProofOfWork::WorkPackage current; - while (true) - try - { - bool completed = false; - ProofOfWork::Solution solution; - f.onSolutionFound([&](ProofOfWork::Solution sol) - { - solution = sol; - return completed = true; - }); - for (unsigned i = 0; !completed; ++i) - { - if (current) - cnote << "Mining on PoWhash" << current.headerHash << ": " << f.miningProgress(); - else - cnote << "Getting work package..."; - Json::Value v = rpc.eth_getWork(); - h256 hh(v[0].asString()); - if (hh != current.headerHash) - { - current.headerHash = hh; - current.seedHash = h256(v[1].asString()); - current.boundary = h256(fromHex(v[2].asString()), h256::AlignRight); - cnote << "Got work package:" << current.headerHash << " < " << current.boundary; - f.setWork(current); - } - this_thread::sleep_for(chrono::milliseconds(_recheckPeriod)); - } - cnote << "Solution found; submitting [" << solution.nonce << "," << current.headerHash << "," << solution.mixHash << "] to" << _remote << "..."; - bool ok = rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(current.headerHash), "0x" + toString(solution.mixHash)); - if (ok) - clog(HappyChannel) << "Submitted and accepted."; - else - clog(SadChannel) << "Not accepted."; - current.reset(); - } - catch (jsonrpc::JsonRpcException&) - { - for (auto i = 3; --i; this_thread::sleep_for(chrono::seconds(1))) - cerr << "JSON-RPC problem. Probably couldn't connect. Retrying in " << i << "... \r"; - cerr << endl; - } -#endif - exit(0); -} - void stopMiningAfterXBlocks(eth::Client* _c, unsigned _start, unsigned _mining) { if (_c->isMining() && _c->blockChain().details().number - _start == _mining) @@ -440,73 +248,6 @@ void stopMiningAfterXBlocks(eth::Client* _c, unsigned _start, unsigned _mining) int main(int argc, char** argv) { -#if 0 - cout << "\x1b[30mEthBlack\x1b[0m" << endl; - cout << "\x1b[90mEthCoal\x1b[0m" << endl; - cout << "\x1b[37mEthGray\x1b[0m" << endl; - cout << "\x1b[97mEthWhite\x1b[0m" << endl; - cout << "\x1b[31mEthRed\x1b[0m" << endl; - cout << "\x1b[32mEthGreen\x1b[0m" << endl; - cout << "\x1b[33mEthYellow\x1b[0m" << endl; - cout << "\x1b[34mEthBlue\x1b[0m" << endl; - cout << "\x1b[35mEthPurple\x1b[0m" << endl; - cout << "\x1b[36mEthCyan\x1b[0m" << endl; - // High Intensity - cout << "\x1b[91mEthRedI\x1b[0m" << endl; - cout << "\x1b[92mEthLime\x1b[0m" << endl; - cout << "\x1b[93mEthYellowI\x1b[0m" << endl; - cout << "\x1b[94mEthBlueI\x1b[0m" << endl; - cout << "\x1b[95mEthPurpleI\x1b[0m" << endl; - cout << "\x1b[96mEthCyanI\x1b[0m" << endl; - - // Bold - cout << "\x1b[1;30mEthBlackB\x1b[0m" << endl; - cout << "\x1b[1;90mEthCoalB\x1b[0m" << endl; - cout << "\x1b[1;37mEthGrayB\x1b[0m" << endl; - cout << "\x1b[1;97mEthWhiteB\x1b[0m" << endl; - cout << "\x1b[1;31mEthRedB\x1b[0m" << endl; - cout << "\x1b[1;32mEthGreenB\x1b[0m" << endl; - cout << "\x1b[1;33mEthYellowB\x1b[0m" << endl; - cout << "\x1b[1;34mEthBlueB\x1b[0m" << endl; - cout << "\x1b[1;35mEthPurpleB\x1b[0m" << endl; - cout << "\x1b[1;36mEthCyanB\x1b[0m" << endl; - // Bold High Intensity - cout << "\x1b[1;91mEthRedBI\x1b[0m" << endl; - cout << "\x1b[1;92mEthGreenBI\x1b[0m" << endl; - cout << "\x1b[1;93mEthYellowBI\x1b[0m" << endl; - cout << "\x1b[1;94mEthBlueBI\x1b[0m" << endl; - cout << "\x1b[1;95mEthPurpleBI\x1b[0m" << endl; - cout << "\x1b[1;96mEthCyanBI\x1b[0m" << endl; - - // Background - cout << "\x1b[40mEthBlackOn\x1b[0m" << endl; - cout << "\x1b[100mEthCoalOn\x1b[0m" << endl; - cout << "\x1b[47mEthGrayOn\x1b[0m" << endl; - cout << "\x1b[107mEthWhiteOn\x1b[0m" << endl; - cout << "\x1b[41mEthRedOn\x1b[0m" << endl; - cout << "\x1b[42mEthGreenOn\x1b[0m" << endl; - cout << "\x1b[43mEthYellowOn\x1b[0m" << endl; - cout << "\x1b[44mEthBlueOn\x1b[0m" << endl; - cout << "\x1b[45mEthPurpleOn\x1b[0m" << endl; - cout << "\x1b[46mEthCyanOn\x1b[0m" << endl; - // High Intensity backgrounds - cout << "\x1b[101mEthRedOnI\x1b[0m" << endl; - cout << "\x1b[102mEthGreenOnI\x1b[0m" << endl; - cout << "\x1b[103mEthYellowOnI\x1b[0m" << endl; - cout << "\x1b[104mEthBlueOnI\x1b[0m" << endl; - cout << "\x1b[105mEthPurpleOnI\x1b[0m" << endl; - cout << "\x1b[106mEthCyanOnI\x1b[0m" << endl; - - // Underline - cout << "\x1b[4;30mEthBlackU\x1b[0m" << endl; - cout << "\x1b[4;31mEthRedU\x1b[0m" << endl; - cout << "\x1b[4;32mEthGreenU\x1b[0m" << endl; - cout << "\x1b[4;33mEthYellowU\x1b[0m" << endl; - cout << "\x1b[4;34mEthBlueU\x1b[0m" << endl; - cout << "\x1b[4;35mEthPurpleU\x1b[0m" << endl; - cout << "\x1b[4;36mEthCyanU\x1b[0m" << endl; - cout << "\x1b[4;37mEthWhiteU\x1b[0m" << endl; -#endif // Init defaults Defaults::get(); @@ -514,12 +255,6 @@ int main(int argc, char** argv) OperationMode mode = OperationMode::Node; string dbPath; - /// Mining options - MinerType minerType = MinerType::CPU; - unsigned openclPlatform = 0; - unsigned openclDevice = 0; - unsigned miningThreads = UINT_MAX; - /// File name for import/export. string filename; @@ -528,9 +263,6 @@ int main(int argc, char** argv) string exportTo = "latest"; Format exportFormat = Format::Binary; - /// DAG initialisation param. - unsigned initDAG = 0; - /// General params for Node operation NodeMode nodeMode = NodeMode::Full; bool interactive = false; @@ -569,19 +301,9 @@ int main(int argc, char** argv) double etherPrice = 30.679; double blockFees = 15.0; - /// Benchmarking params - bool phoneHome = true; - unsigned benchmarkWarmup = 3; - unsigned benchmarkTrial = 3; - unsigned benchmarkTrials = 5; - // javascript console bool useConsole = false; - /// Farm params - string farmURL = "http://127.0.0.1:8545"; - unsigned farmRecheckPeriod = 500; - /// Wallet password stuff string masterPassword; @@ -603,10 +325,13 @@ int main(int argc, char** argv) beneficiary = config[1].toHash
(); } + MinerCLI m(MinerCLI::OperationMode::None); + for (int i = 1; i < argc; ++i) { string arg = argv[i]; - if (arg == "--listen-ip" && i + 1 < argc) + if (m.interpretOption(i, argc, argv)) {} + else if (arg == "--listen-ip" && i + 1 < argc) listenIP = argv[++i]; else if ((arg == "-l" || arg == "--listen" || arg == "--listen-port") && i + 1 < argc) { @@ -642,52 +367,6 @@ int main(int argc, char** argv) mode = OperationMode::Export; filename = argv[++i]; } - else if ((arg == "-F" || arg == "--farm") && i + 1 < argc) - { - mode = OperationMode::Farm; - farmURL = argv[++i]; - } - else if (arg == "--farm-recheck" && i + 1 < argc) - try { - farmRecheckPeriod = stol(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } - else if (arg == "--opencl-platform" && i + 1 < argc) - try { - openclPlatform = stol(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } - else if (arg == "--opencl-device" && i + 1 < argc) - try { - openclDevice = stol(argv[++i]); - miningThreads = 1; - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } - else if (arg == "--phone-home" && i + 1 < argc) - { - string m = argv[++i]; - if (isTrue(m)) - phoneHome = true; - else if (isFalse(m)) - phoneHome = false; - else - { - cerr << "Bad " << arg << " option: " << m << endl; - return -1; - } - } else if (arg == "--format" && i + 1 < argc) { string m = argv[++i]; @@ -733,33 +412,6 @@ int main(int argc, char** argv) cerr << "Bad " << arg << " option: " << argv[i] << endl; return -1; } - else if (arg == "--benchmark-warmup" && i + 1 < argc) - try { - benchmarkWarmup = stol(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } - else if (arg == "--benchmark-trial" && i + 1 < argc) - try { - benchmarkTrial = stol(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } - else if (arg == "--benchmark-trials" && i + 1 < argc) - try { - benchmarkTrials = stol(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } else if (arg == "-K" || arg == "--kill-blockchain" || arg == "--kill") killChain = WithExisting::Kill; else if (arg == "-R" || arg == "--rebuild") @@ -784,17 +436,6 @@ int main(int argc, char** argv) cerr << "Bad " << arg << " option: " << argv[i] << endl; return -1; } - else if (arg == "-C" || arg == "--cpu") - minerType = MinerType::CPU; - else if (arg == "-G" || arg == "--opencl") - { - minerType = MinerType::GPU; - miningThreads = 1; - /*<< " -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])); @@ -822,64 +463,6 @@ int main(int argc, char** argv) } 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) - { - string m = boost::to_lower_copy(string(argv[++i])); - mode = OperationMode::DAGInit; - if (m == "next") - initDAG = PendingBlock; - else if (m == "this") - initDAG = LatestBlock; - else - try - { - initDAG = stol(m); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << m << endl; - return -1; - } - } - else if ((arg == "-w" || arg == "--check-pow") && i + 4 < argc) - { - string m; - try - { - BlockInfo bi; - m = boost::to_lower_copy(string(argv[++i])); - h256 powHash(m); - m = boost::to_lower_copy(string(argv[++i])); - h256 seedHash; - if (m.size() == 64 || m.size() == 66) - seedHash = h256(m); - else - seedHash = EthashAux::seedHash(stol(m)); - m = boost::to_lower_copy(string(argv[++i])); - bi.difficulty = u256(m); - auto boundary = bi.boundary(); - m = boost::to_lower_copy(string(argv[++i])); - bi.nonce = h64(m); - auto r = EthashAux::eval(bi.seedHash(), powHash, bi.nonce); - bool valid = r.value < boundary; - cout << (valid ? "VALID :-)" : "INVALID :-(") << endl; - cout << r.value << (valid ? " < " : " >= ") << boundary << endl; - cout << " where " << boundary << " = 2^256 / " << bi.difficulty << endl; - cout << " and " << r.value << " = ethash(" << powHash << ", " << bi.nonce << ")" << endl; - cout << " with seed as " << seedHash << endl; - if (valid) - cout << "(mixHash = " << r.mixHash << ")" << endl; - cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(bi.seedHash())->data()) << endl; - exit(0); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << m << endl; - return -1; - } - } - else if (arg == "-M" || arg == "--benchmark") - mode = OperationMode::Benchmark; else if ((arg == "-B" || arg == "--block-fees") && i + 1 < argc) { try @@ -942,17 +525,6 @@ int main(int argc, char** argv) return -1; } } - else if ((arg == "-t" || arg == "--mining-threads") && i + 1 < argc) - { - try { - miningThreads = stol(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } - } else if (arg == "-b" || arg == "--bootstrap") bootstrap = true; else if (arg == "-f" || arg == "--force-mining") @@ -1003,6 +575,8 @@ int main(int argc, char** argv) } } + m.execute(); + KeyManager keyManager; for (auto const& s: passwordsToNote) keyManager.notePassword(s); @@ -1016,26 +590,6 @@ int main(int argc, char** argv) if (sessionKey) signingKey = sessionKey; - if (minerType == MinerType::CPU) - ProofOfWork::CPUMiner::setNumInstances(miningThreads); - else if (minerType == MinerType::GPU) - { - ProofOfWork::GPUMiner::setDefaultPlatform(openclPlatform); - ProofOfWork::GPUMiner::setDefaultDevice(openclDevice); - ProofOfWork::GPUMiner::setNumInstances(miningThreads); - } - - // Two codepaths is necessary since named block require database, but numbered - // blocks are superuseful to have when database is already open in another process. - if (mode == OperationMode::DAGInit && !(initDAG == LatestBlock || initDAG == PendingBlock)) - doInitDAG(initDAG); - - if (mode == OperationMode::Benchmark) - doBenchmark(minerType, phoneHome, benchmarkWarmup, benchmarkTrial, benchmarkTrials); - - if (mode == OperationMode::Farm) - doFarm(minerType, farmURL, farmRecheckPeriod); - if (!clientName.empty()) clientName += "/"; @@ -1074,44 +628,6 @@ int main(int argc, char** argv) netPrefs, &nodesState); - if (mode == OperationMode::DAGInit) - doInitDAG(web3.ethereum()->blockChain().number() + (initDAG == PendingBlock ? 30000 : 0)); - - 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); - } - - for (auto const& s: toImport) - { - keyManager.import(s, "Imported key (UNSAFE)"); - if (!signingKey) - signingKey = toAddress(s); - } - - if (keyManager.accounts().empty()) - keyManager.import(Secret::random(), "Default key"); - auto toNumber = [&](string const& s) -> unsigned { if (s == "latest") return web3.ethereum()->number(); @@ -1175,7 +691,42 @@ int main(int argc, char** argv) return 0; } - cout << credits(); + 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); + } + + for (auto const& s: toImport) + { + keyManager.import(s, "Imported key (UNSAFE)"); + if (!signingKey) + signingKey = toAddress(s); + } + + if (keyManager.accounts().empty()) + keyManager.import(Secret::random(), "Default key"); + + cout << ethCredits(); web3.setIdealPeerCount(peers); std::shared_ptr gasPricer = make_shared(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000)); eth::Client* c = nodeMode == NodeMode::Full ? web3.ethereum() : nullptr; @@ -1184,7 +735,7 @@ int main(int argc, char** argv) { c->setGasPricer(gasPricer); c->setForceMining(forceMining); - c->setTurboMining(minerType == MinerType::GPU); + c->setTurboMining(m.minerType() == MinerCLI::MinerType::GPU); c->setAddress(beneficiary); c->setNetworkId(networkId); } diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h new file mode 100644 index 000000000..2a2aca10e --- /dev/null +++ b/ethminer/MinerAux.h @@ -0,0 +1,483 @@ +#pragma once + +/* + 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 main.cpp + * @author Gav Wood + * @date 2014 + * Ethereum client. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#if ETH_JSONRPC || !ETH_TRUE +#include +#include +#include +#endif +#include "BuildInfo.h" +#if ETH_JSONRPC || !ETH_TRUE +#include "PhoneHome.h" +#include "Farm.h" +#endif +using namespace std; +using namespace dev; +using namespace dev::eth; +using namespace boost::algorithm; +using dev::eth::Instruction; + +#undef RETURN + +bool isTrue(std::string const& _m) +{ + return _m == "on" || _m == "yes" || _m == "true" || _m == "1"; +} + +bool isFalse(std::string const& _m) +{ + return _m == "off" || _m == "no" || _m == "false" || _m == "0"; +} + +inline std::string credits() +{ + std::ostringstream out; + out + << "Ethereum (++) " << dev::Version << endl + << " Code by Gav Wood et al, (c) 2013, 2014, 2015." << endl; + return out.str(); +} + +class BadArgument: public Exception {}; + +class MinerCLI +{ +public: + enum class OperationMode + { + None, + DAGInit, + Benchmark, + Farm + }; + + MinerCLI(OperationMode _mode = OperationMode::None): mode(_mode) {} + + bool interpretOption(int& i, int argc, char** argv) + { + string arg = argv[i]; + if ((arg == "-F" || arg == "--farm") && i + 1 < argc) + { + mode = OperationMode::Farm; + farmURL = argv[++i]; + } + else if (arg == "--farm-recheck" && i + 1 < argc) + try { + farmRecheckPeriod = stol(argv[++i]); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + throw BadArgument(); + } + else if (arg == "--opencl-platform" && i + 1 < argc) + try { + openclPlatform = stol(argv[++i]); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + throw BadArgument(); + } + else if (arg == "--opencl-device" && i + 1 < argc) + try { + openclDevice = stol(argv[++i]); + miningThreads = 1; + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + throw BadArgument(); + } + else if (arg == "--phone-home" && i + 1 < argc) + { + string m = argv[++i]; + if (isTrue(m)) + phoneHome = true; + else if (isFalse(m)) + phoneHome = false; + else + { + cerr << "Bad " << arg << " option: " << m << endl; + throw BadArgument(); + } + } + else if (arg == "--benchmark-warmup" && i + 1 < argc) + try { + benchmarkWarmup = stol(argv[++i]); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + throw BadArgument(); + } + else if (arg == "--benchmark-trial" && i + 1 < argc) + try { + benchmarkTrial = stol(argv[++i]); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + throw BadArgument(); + } + else if (arg == "--benchmark-trials" && i + 1 < argc) + try { + benchmarkTrials = stol(argv[++i]); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + throw BadArgument(); + } + else if (arg == "-C" || arg == "--cpu") + m_minerType = MinerType::CPU; + else if (arg == "-G" || arg == "--opencl") + { + m_minerType = MinerType::GPU; + miningThreads = 1; + } + else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc) + { + string m = boost::to_lower_copy(string(argv[++i])); + mode = OperationMode::DAGInit; + try + { + initDAG = stol(m); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << m << endl; + throw BadArgument(); + } + } + else if ((arg == "-w" || arg == "--check-pow") && i + 4 < argc) + { + string m; + try + { + BlockInfo bi; + m = boost::to_lower_copy(string(argv[++i])); + h256 powHash(m); + m = boost::to_lower_copy(string(argv[++i])); + h256 seedHash; + if (m.size() == 64 || m.size() == 66) + seedHash = h256(m); + else + seedHash = EthashAux::seedHash(stol(m)); + m = boost::to_lower_copy(string(argv[++i])); + bi.difficulty = u256(m); + auto boundary = bi.boundary(); + m = boost::to_lower_copy(string(argv[++i])); + bi.nonce = h64(m); + auto r = EthashAux::eval(bi.seedHash(), powHash, bi.nonce); + bool valid = r.value < boundary; + cout << (valid ? "VALID :-)" : "INVALID :-(") << endl; + cout << r.value << (valid ? " < " : " >= ") << boundary << endl; + cout << " where " << boundary << " = 2^256 / " << bi.difficulty << endl; + cout << " and " << r.value << " = ethash(" << powHash << ", " << bi.nonce << ")" << endl; + cout << " with seed as " << seedHash << endl; + if (valid) + cout << "(mixHash = " << r.mixHash << ")" << endl; + cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(bi.seedHash())->data()) << endl; + exit(0); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << m << endl; + throw BadArgument(); + } + } + else if (arg == "-M" || arg == "--benchmark") + mode = OperationMode::Benchmark; + else if ((arg == "-t" || arg == "--mining-threads") && i + 1 < argc) + { + try { + miningThreads = stol(argv[++i]); + } + catch (...) + { + cerr << "Bad " << arg << " option: " << argv[i] << endl; + throw BadArgument(); + } + } + else + return false; + return true; + } + + void execute() + { + if (m_minerType == MinerType::CPU) + ProofOfWork::CPUMiner::setNumInstances(miningThreads); + else if (m_minerType == MinerType::GPU) + { + ProofOfWork::GPUMiner::setDefaultPlatform(openclPlatform); + ProofOfWork::GPUMiner::setDefaultDevice(openclDevice); + ProofOfWork::GPUMiner::setNumInstances(miningThreads); + } + if (mode == OperationMode::DAGInit) + doInitDAG(initDAG); + else if (mode == OperationMode::Benchmark) + doBenchmark(m_minerType, phoneHome, benchmarkWarmup, benchmarkTrial, benchmarkTrials); + else if (mode == OperationMode::Farm) + doFarm(m_minerType, farmURL, farmRecheckPeriod); + } + + static void streamHelp(ostream& _out) + { + _out +#if ETH_JSONRPC || !ETH_TRUE + << "Work farming mode:" << endl + << " -F,--farm Put into mining farm mode with the work server at URL (default: http://127.0.0.1:8545)" << endl + << " --farm-recheck Leave n ms between checks for changed work (default: 500)." << endl +#endif + << "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 + << " --benchmark-trial Set the duration for each trial for the benchmark tests (default: 3)." << endl + << " --benchmark-trials Set the duration of warmup for the benchmark tests (default: 5)." << endl +#if ETH_JSONRPC || !ETH_TRUE + << " --phone-home When benchmarking, publish results (default: on)" << endl +#endif + << "DAG creation mode:" << endl + << " -D,--create-dag Create the DAG in preparation for mining on given block and exit." << endl + << "Mining configuration:" << endl + << " -C,--cpu When mining, use the CPU." << endl + << " -G,--opencl When mining use the GPU via OpenCL." << endl + << " --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 + ; + } + + enum class MinerType + { + CPU, + GPU + }; + + MinerType minerType() const { return m_minerType; } + +private: + void doInitDAG(unsigned _n) + { + BlockInfo bi; + bi.number = _n; + cout << "Initializing DAG for epoch beginning #" << (bi.number / 30000 * 30000) << " (seedhash " << bi.seedHash().abridged() << "). This will take a while." << endl; + Ethash::prep(bi); + exit(0); + } + + void doBenchmark(MinerType _m, bool _phoneHome, unsigned _warmupDuration = 15, unsigned _trialDuration = 3, unsigned _trials = 5) + { + BlockInfo genesis; + genesis.difficulty = 1 << 18; + cdebug << genesis.boundary(); + + GenericFarm f; + f.onSolutionFound([&](ProofOfWork::Solution) { return false; }); + + string platformInfo = _m == MinerType::CPU ? ProofOfWork::CPUMiner::platformInfo() : _m == MinerType::GPU ? ProofOfWork::GPUMiner::platformInfo() : ""; + cout << "Benchmarking on platform: " << platformInfo << endl; + + cout << "Preparing DAG..." << endl; + Ethash::prep(genesis); + + genesis.difficulty = u256(1) << 63; + genesis.noteDirty(); + f.setWork(genesis); + if (_m == MinerType::CPU) + f.startCPU(); + else if (_m == MinerType::GPU) + f.startGPU(); + + map results; + uint64_t mean = 0; + uint64_t innerMean = 0; + for (unsigned i = 0; i <= _trials; ++i) + { + if (!i) + cout << "Warming up..." << endl; + else + cout << "Trial " << i << "... " << flush; + this_thread::sleep_for(chrono::seconds(i ? _trialDuration : _warmupDuration)); + + auto mp = f.miningProgress(); + f.resetMiningProgress(); + if (!i) + continue; + auto rate = mp.rate(); + + cout << rate << endl; + results[rate] = mp; + mean += rate; + } + f.stop(); + int j = -1; + for (auto const& r: results) + if (++j > 0 && j < (int)_trials - 1) + innerMean += r.second.rate(); + innerMean /= (_trials - 2); + cout << "min/mean/max: " << results.begin()->second.rate() << "/" << (mean / _trials) << "/" << results.rbegin()->second.rate() << " H/s" << endl; + cout << "inner mean: " << innerMean << " H/s" << endl; + + (void)_phoneHome; + #if ETH_JSONRPC || !ETH_TRUE + if (_phoneHome) + { + cout << "Phoning home to find world ranking..." << endl; + jsonrpc::HttpClient client("http://gav.ethdev.com:3000/benchmark"); + PhoneHome rpc(client); + try + { + unsigned ranking = rpc.report_benchmark(platformInfo, innerMean); + cout << "Ranked: " << ranking << " of all benchmarks." << endl; + } + catch (...) + { + cout << "Error phoning home. ET is sad." << endl; + } + } + #endif + exit(0); + } + + void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod) + { + (void)_m; + (void)_remote; + (void)_recheckPeriod; + #if ETH_JSONRPC || !ETH_TRUE + jsonrpc::HttpClient client(_remote); + + Farm rpc(client); + GenericFarm f; + if (_m == MinerType::CPU) + f.startCPU(); + else if (_m == MinerType::GPU) + f.startGPU(); + + ProofOfWork::WorkPackage current; + while (true) + try + { + bool completed = false; + ProofOfWork::Solution solution; + f.onSolutionFound([&](ProofOfWork::Solution sol) + { + solution = sol; + return completed = true; + }); + for (unsigned i = 0; !completed; ++i) + { + if (current) + cnote << "Mining on PoWhash" << current.headerHash << ": " << f.miningProgress(); + else + cnote << "Getting work package..."; + Json::Value v = rpc.eth_getWork(); + h256 hh(v[0].asString()); + if (hh != current.headerHash) + { + current.headerHash = hh; + current.seedHash = h256(v[1].asString()); + current.boundary = h256(fromHex(v[2].asString()), h256::AlignRight); + cnote << "Got work package:"; + cnote << " Header-hash:" << current.headerHash.hex(); + cnote << " Seedhash:" << current.seedHash.hex(); + cnote << " Target: " << h256(current.boundary).hex(); + f.setWork(current); + } + this_thread::sleep_for(chrono::milliseconds(_recheckPeriod)); + } + cnote << "Solution found; Submitting to" << _remote << "..."; + cnote << " Nonce:" << solution.nonce.hex(); + cnote << " Mixhash:" << solution.mixHash.hex(); + cnote << " Header-hash:" << current.headerHash.hex(); + cnote << " Seedhash:" << current.seedHash.hex(); + cnote << " Target: " << h256(current.boundary).hex(); + cnote << " Ethash: " << h256(EthashAux::eval(current.seedHash, current.headerHash, solution.nonce).value).hex(); + if (EthashAux::eval(current.seedHash, current.headerHash, solution.nonce).value < current.boundary) + { + bool ok = rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(current.headerHash), "0x" + toString(solution.mixHash)); + if (ok) + cnote << "B-) Submitted and accepted."; + else + cwarn << ":-( Not accepted."; + } + else + cwarn << "FAILURE: GPU gave incorrect result!"; + current.reset(); + } + catch (jsonrpc::JsonRpcException&) + { + for (auto i = 3; --i; this_thread::sleep_for(chrono::seconds(1))) + cerr << "JSON-RPC problem. Probably couldn't connect. Retrying in " << i << "... \r"; + cerr << endl; + } + #endif + exit(0); + } + + /// Operating mode. + OperationMode mode; + + /// Mining options + MinerType m_minerType = MinerType::CPU; + unsigned openclPlatform = 0; + unsigned openclDevice = 0; + unsigned miningThreads = UINT_MAX; + + /// DAG initialisation param. + unsigned initDAG = 0; + + /// Benchmarking params + bool phoneHome = true; + unsigned benchmarkWarmup = 3; + unsigned benchmarkTrial = 3; + unsigned benchmarkTrials = 5; + + /// Farm params + string farmURL = "http://127.0.0.1:8545"; + unsigned farmRecheckPeriod = 500; + +}; diff --git a/ethminer/main.cpp b/ethminer/main.cpp index a19934ba0..5b82db471 100644 --- a/ethminer/main.cpp +++ b/ethminer/main.cpp @@ -25,441 +25,48 @@ #include #include #include - #include #include - #include -#include -#include -#include -#include -#include -#include -#if ETH_JSONRPC || !ETH_TRUE -#include -#include -#include -#endif -#include "BuildInfo.h" -#if ETH_JSONRPC || !ETH_TRUE -#include "PhoneHome.h" -#include "Farm.h" -#endif +#include "MinerAux.h" using namespace std; using namespace dev; using namespace dev::eth; using namespace boost::algorithm; -using dev::eth::Instruction; #undef RETURN -bool isTrue(std::string const& _m) -{ - return _m == "on" || _m == "yes" || _m == "true" || _m == "1"; -} - -bool isFalse(std::string const& _m) -{ - return _m == "off" || _m == "no" || _m == "false" || _m == "0"; -} - void help() { cout << "Usage ethminer [OPTIONS]" << endl - << "Options:" << endl << endl -#if ETH_JSONRPC || !ETH_TRUE - << "Work farming mode:" << endl - << " -F,--farm Put into mining farm mode with the work server at URL (default: http://127.0.0.1:8545)" << endl - << " --farm-recheck Leave n ms between checks for changed work (default: 500)." << endl -#endif - << "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 - << " --benchmark-trial Set the duration for each trial for the benchmark tests (default: 3)." << endl - << " --benchmark-trials Set the duration of warmup for the benchmark tests (default: 5)." << endl -#if ETH_JSONRPC || !ETH_TRUE - << " --phone-home When benchmarking, publish results (default: on)" << endl -#endif - << "DAG creation mode:" << endl - << " -D,--create-dag Create the DAG in preparation for mining on given block and exit." << endl + << "Options:" << endl << endl; + MinerCLI::streamHelp(cout); + cout << "General Options:" << endl - << " -C,--cpu When mining, use the CPU." << endl - << " -G,--opencl When mining use the GPU via OpenCL." << endl - << " --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 << " -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 ; - exit(0); -} - -string credits() -{ - std::ostringstream cout; - cout - << "Ethereum (++) " << dev::Version << endl - << " Code by Gav Wood et al, (c) 2013, 2014, 2015." << endl - << " Based on a design by Vitalik Buterin." << endl << endl; - return cout.str(); + exit(0); } void version() { - cout << "eth version " << dev::Version << endl; - cout << "eth network protocol version: " << dev::eth::c_protocolVersion << endl; - cout << "Client database version: " << dev::eth::c_databaseVersion << endl; + cout << "ethminer version " << dev::Version << endl; cout << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl; exit(0); } -void doInitDAG(unsigned _n) -{ - BlockInfo bi; - bi.number = _n; - cout << "Initializing DAG for epoch beginning #" << (bi.number / 30000 * 30000) << " (seedhash " << bi.seedHash().abridged() << "). This will take a while." << endl; - Ethash::prep(bi); - exit(0); -} - -enum class OperationMode -{ - DAGInit, - Benchmark, - Farm -}; - -enum class MinerType -{ - CPU, - GPU -}; - -void doBenchmark(MinerType _m, bool _phoneHome, unsigned _warmupDuration = 15, unsigned _trialDuration = 3, unsigned _trials = 5) -{ - BlockInfo genesis; - genesis.difficulty = 1 << 18; - cdebug << genesis.boundary(); - - GenericFarm f; - f.onSolutionFound([&](ProofOfWork::Solution) { return false; }); - - string platformInfo = _m == MinerType::CPU ? ProofOfWork::CPUMiner::platformInfo() : _m == MinerType::GPU ? ProofOfWork::GPUMiner::platformInfo() : ""; - cout << "Benchmarking on platform: " << platformInfo << endl; - - cout << "Preparing DAG..." << endl; - Ethash::prep(genesis); - - genesis.difficulty = u256(1) << 63; - genesis.noteDirty(); - f.setWork(genesis); - if (_m == MinerType::CPU) - f.startCPU(); - else if (_m == MinerType::GPU) - f.startGPU(); - - map results; - uint64_t mean = 0; - uint64_t innerMean = 0; - for (unsigned i = 0; i <= _trials; ++i) - { - if (!i) - cout << "Warming up..." << endl; - else - cout << "Trial " << i << "... " << flush; - this_thread::sleep_for(chrono::seconds(i ? _trialDuration : _warmupDuration)); - - auto mp = f.miningProgress(); - f.resetMiningProgress(); - if (!i) - continue; - auto rate = mp.rate(); - - cout << rate << endl; - results[rate] = mp; - mean += rate; - if (i > 1 && i < 5) - innerMean += rate; - } - f.stop(); - innerMean /= (_trials - 2); - cout << "min/mean/max: " << results.begin()->second.rate() << "/" << (mean / _trials) << "/" << results.rbegin()->second.rate() << " H/s" << endl; - cout << "inner mean: " << innerMean << " H/s" << endl; - - (void)_phoneHome; -#if ETH_JSONRPC || !ETH_TRUE - if (_phoneHome) - { - cout << "Phoning home to find world ranking..." << endl; - jsonrpc::HttpClient client("http://gav.ethdev.com:3000/benchmark"); - PhoneHome rpc(client); - try - { - unsigned ranking = rpc.report_benchmark(platformInfo, innerMean); - cout << "Ranked: " << ranking << " of all benchmarks." << endl; - } - catch (...) - { - cout << "Error phoning home. ET is sad." << endl; - } - } -#endif - exit(0); -} - -struct HappyChannel: public LogChannel { static const char* name() { return ":-D"; } static const int verbosity = 1; }; -struct SadChannel: public LogChannel { static const char* name() { return ":-("; } static const int verbosity = 1; }; - -void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod) -{ - (void)_m; - (void)_remote; - (void)_recheckPeriod; -#if ETH_JSONRPC || !ETH_TRUE - jsonrpc::HttpClient client(_remote); - - Farm rpc(client); - GenericFarm f; - if (_m == MinerType::CPU) - f.startCPU(); - else if (_m == MinerType::GPU) - f.startGPU(); - - ProofOfWork::WorkPackage current; - while (true) - try - { - bool completed = false; - ProofOfWork::Solution solution; - f.onSolutionFound([&](ProofOfWork::Solution sol) - { - solution = sol; - return completed = true; - }); - for (unsigned i = 0; !completed; ++i) - { - if (current) - cnote << "Mining on PoWhash" << current.headerHash << ": " << f.miningProgress(); - else - cnote << "Getting work package..."; - Json::Value v = rpc.eth_getWork(); - h256 hh(v[0].asString()); - if (hh != current.headerHash) - { - current.headerHash = hh; - current.seedHash = h256(v[1].asString()); - current.boundary = h256(fromHex(v[2].asString()), h256::AlignRight); - cnote << "Got work package:"; - cnote << " Header-hash:" << current.headerHash.hex(); - cnote << " Seedhash:" << current.seedHash.hex(); - cnote << " Target: " << h256(current.boundary).hex(); - f.setWork(current); - } - this_thread::sleep_for(chrono::milliseconds(_recheckPeriod)); - } - cnote << "Solution found; Submitting to" << _remote << "..."; - cnote << " Nonce:" << solution.nonce.hex(); - cnote << " Mixhash:" << solution.mixHash.hex(); - cnote << " Header-hash:" << current.headerHash.hex(); - cnote << " Seedhash:" << current.seedHash.hex(); - cnote << " Target: " << h256(current.boundary).hex(); - cnote << " Ethash: " << h256(EthashAux::eval(current.seedHash, current.headerHash, solution.nonce).value).hex(); - if (EthashAux::eval(current.seedHash, current.headerHash, solution.nonce).value < current.boundary) - { - bool ok = rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(current.headerHash), "0x" + toString(solution.mixHash)); - if (ok) - clog(HappyChannel) << "Submitted and accepted."; - else - clog(SadChannel) << "Not accepted."; - } - else - cwarn << "FAILURE: GPU gave incorrect result!"; - current.reset(); - } - catch (jsonrpc::JsonRpcException&) - { - for (auto i = 3; --i; this_thread::sleep_for(chrono::seconds(1))) - cerr << "JSON-RPC problem. Probably couldn't connect. Retrying in " << i << "... \r"; - cerr << endl; - } -#endif - exit(0); -} - int main(int argc, char** argv) { - /// Operating mode. - OperationMode mode = OperationMode::Farm; - - /// Mining options - MinerType minerType = MinerType::CPU; - unsigned openclPlatform = 0; - unsigned openclDevice = 0; - unsigned miningThreads = UINT_MAX; - - /// DAG initialisation param. - unsigned initDAG = 0; - - /// Benchmarking params - bool phoneHome = true; - unsigned benchmarkWarmup = 3; - unsigned benchmarkTrial = 3; - unsigned benchmarkTrials = 5; - - /// Farm params - string farmURL = "http://127.0.0.1:8545"; - unsigned farmRecheckPeriod = 500; + MinerCLI m(MinerCLI::OperationMode::Farm); for (int i = 1; i < argc; ++i) { string arg = argv[i]; - if ((arg == "-F" || arg == "--farm") && i + 1 < argc) - { - mode = OperationMode::Farm; - farmURL = argv[++i]; - } - else if (arg == "--farm-recheck" && i + 1 < argc) - try { - farmRecheckPeriod = stol(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } - else if (arg == "--opencl-platform" && i + 1 < argc) - try { - openclPlatform = stol(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } - else if (arg == "--opencl-device" && i + 1 < argc) - try { - openclDevice = stol(argv[++i]); - miningThreads = 1; - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } - else if (arg == "--phone-home" && i + 1 < argc) - { - string m = argv[++i]; - if (isTrue(m)) - phoneHome = true; - else if (isFalse(m)) - phoneHome = false; - else - { - cerr << "Bad " << arg << " option: " << m << endl; - return -1; - } - } - else if (arg == "--benchmark-warmup" && i + 1 < argc) - try { - benchmarkWarmup = stol(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } - else if (arg == "--benchmark-trial" && i + 1 < argc) - try { - benchmarkTrial = stol(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } - else if (arg == "--benchmark-trials" && i + 1 < argc) - try { - benchmarkTrials = stol(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } - else if (arg == "-C" || arg == "--cpu") - minerType = MinerType::CPU; - else if (arg == "-G" || arg == "--opencl") - { - minerType = MinerType::GPU; - miningThreads = 1; - } - else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc) - { - string m = boost::to_lower_copy(string(argv[++i])); - mode = OperationMode::DAGInit; - try - { - initDAG = stol(m); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << m << endl; - return -1; - } - } - else if ((arg == "-w" || arg == "--check-pow") && i + 4 < argc) - { - string m; - try - { - BlockInfo bi; - m = boost::to_lower_copy(string(argv[++i])); - h256 powHash(m); - m = boost::to_lower_copy(string(argv[++i])); - h256 seedHash; - if (m.size() == 64 || m.size() == 66) - seedHash = h256(m); - else - seedHash = EthashAux::seedHash(stol(m)); - m = boost::to_lower_copy(string(argv[++i])); - bi.difficulty = u256(m); - auto boundary = bi.boundary(); - m = boost::to_lower_copy(string(argv[++i])); - bi.nonce = h64(m); - auto r = EthashAux::eval(bi.seedHash(), powHash, bi.nonce); - bool valid = r.value < boundary; - cout << (valid ? "VALID :-)" : "INVALID :-(") << endl; - cout << r.value << (valid ? " < " : " >= ") << boundary << endl; - cout << " where " << boundary << " = 2^256 / " << bi.difficulty << endl; - cout << " and " << r.value << " = ethash(" << powHash << ", " << bi.nonce << ")" << endl; - cout << " with seed as " << seedHash << endl; - if (valid) - cout << "(mixHash = " << r.mixHash << ")" << endl; - cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(bi.seedHash())->data()) << endl; - exit(0); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << m << endl; - return -1; - } - } - else if (arg == "-M" || arg == "--benchmark") - mode = OperationMode::Benchmark; - else if ((arg == "-t" || arg == "--mining-threads") && i + 1 < argc) - { - try { - miningThreads = stol(argv[++i]); - } - catch (...) - { - cerr << "Bad " << arg << " option: " << argv[i] << endl; - return -1; - } - } + if (m.interpretOption(i, argc, argv)) + {} else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc) g_logVerbosity = atoi(argv[++i]); else if (arg == "-h" || arg == "--help") @@ -473,23 +80,7 @@ int main(int argc, char** argv) } } - if (minerType == MinerType::CPU) - ProofOfWork::CPUMiner::setNumInstances(miningThreads); - else if (minerType == MinerType::GPU) - { - ProofOfWork::GPUMiner::setDefaultPlatform(openclPlatform); - ProofOfWork::GPUMiner::setDefaultDevice(openclDevice); - ProofOfWork::GPUMiner::setNumInstances(miningThreads); - } - - if (mode == OperationMode::DAGInit) - doInitDAG(initDAG); - - if (mode == OperationMode::Benchmark) - doBenchmark(minerType, phoneHome, benchmarkWarmup, benchmarkTrial, benchmarkTrials); - - if (mode == OperationMode::Farm) - doFarm(minerType, farmURL, farmRecheckPeriod); + m.execute(); return 0; } diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index ff7fe47e7..f6872ae95 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -146,8 +146,8 @@ void Ethash::CPUMiner::workLoop() 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); + if (!(hashCount % 100)) + accumulateHashes(100); } } diff --git a/libethcore/EthashAux.h b/libethcore/EthashAux.h index 3f876f442..b09f6465f 100644 --- a/libethcore/EthashAux.h +++ b/libethcore/EthashAux.h @@ -19,6 +19,8 @@ * @date 2014 */ +#pragma once + #include #include #include From 97d7349bb5f994a887e05d206a55f0ec9aa7642e Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 18 May 2015 17:26:57 +0200 Subject: [PATCH 131/157] Point at real URL for phoning home. --- ethminer/MinerAux.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 2a2aca10e..31e66d94a 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -366,7 +366,7 @@ private: if (_phoneHome) { cout << "Phoning home to find world ranking..." << endl; - jsonrpc::HttpClient client("http://gav.ethdev.com:3000/benchmark"); + jsonrpc::HttpClient client("http://gav.ethdev.com:3000"); PhoneHome rpc(client); try { From 9fcbacc95cea036fc27f53596d49b8bae35b3f48 Mon Sep 17 00:00:00 2001 From: subtly Date: Mon, 18 May 2015 17:35:34 +0200 Subject: [PATCH 132/157] remove apple check, as getpwuid is *nx-safe --- io_posix.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/io_posix.c b/io_posix.c index 1fe82973f..c9a17d845 100644 --- a/io_posix.c +++ b/io_posix.c @@ -26,10 +26,8 @@ #include #include #include -#if defined(__APPLE__) #include #include -#endif FILE* ethash_fopen(char const* file_name, char const* mode) { @@ -93,14 +91,12 @@ bool ethash_get_default_dirname(char* strbuf, size_t buffsize) static const char dir_suffix[] = ".ethash/"; strbuf[0] = '\0'; char* home_dir = getenv("HOME"); -#if defined(__APPLE__) if (!home_dir || strlen(home_dir) == 0) { struct passwd* pwd = getpwuid(getuid()); if (pwd) home_dir = pwd->pw_dir; } -#endif size_t len = strlen(home_dir); if (!ethash_strncat(strbuf, buffsize, home_dir, len)) { From 67e1d52f2ce884c870d89b436e0b9fb72b04730b Mon Sep 17 00:00:00 2001 From: subtly Date: Mon, 18 May 2015 18:09:41 +0200 Subject: [PATCH 133/157] Import changes into MinerAux and retain pointer to dag. --- ethminer/MinerAux.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 31e66d94a..0441bc412 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -398,6 +399,7 @@ private: f.startGPU(); ProofOfWork::WorkPackage current; + EthashAux::FullType dag; while (true) try { @@ -416,10 +418,13 @@ private: cnote << "Getting work package..."; Json::Value v = rpc.eth_getWork(); h256 hh(v[0].asString()); + h256 newSeedHash(v[1].asString()); + if (!(dag = EthashAux::full(newSeedHash, true))) + BOOST_THROW_EXCEPTION(DAGCreationFailure()); if (hh != current.headerHash) { current.headerHash = hh; - current.seedHash = h256(v[1].asString()); + current.seedHash = newSeedHash; current.boundary = h256(fromHex(v[2].asString()), h256::AlignRight); cnote << "Got work package:"; cnote << " Header-hash:" << current.headerHash.hex(); From 0768814d7332eb695438e19efb15b01ae3264754 Mon Sep 17 00:00:00 2001 From: subtly Date: Mon, 18 May 2015 18:10:59 +0200 Subject: [PATCH 134/157] reverse commit for ethash --- libethash/io_posix.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/libethash/io_posix.c b/libethash/io_posix.c index 1fe82973f..80046252d 100644 --- a/libethash/io_posix.c +++ b/libethash/io_posix.c @@ -26,10 +26,6 @@ #include #include #include -#if defined(__APPLE__) -#include -#include -#endif FILE* ethash_fopen(char const* file_name, char const* mode) { @@ -93,14 +89,6 @@ bool ethash_get_default_dirname(char* strbuf, size_t buffsize) static const char dir_suffix[] = ".ethash/"; strbuf[0] = '\0'; char* home_dir = getenv("HOME"); -#if defined(__APPLE__) - if (!home_dir || strlen(home_dir) == 0) - { - struct passwd* pwd = getpwuid(getuid()); - if (pwd) - home_dir = pwd->pw_dir; - } -#endif size_t len = strlen(home_dir); if (!ethash_strncat(strbuf, buffsize, home_dir, len)) { From 07b0ff85ffcc045991a9c97cf43640a9dbf95271 Mon Sep 17 00:00:00 2001 From: subtly Date: Mon, 18 May 2015 18:11:58 +0200 Subject: [PATCH 135/157] reverse commit for ethash --- libethash/io_win32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libethash/io_win32.c b/libethash/io_win32.c index 34f1aaa77..e6e332b9f 100644 --- a/libethash/io_win32.c +++ b/libethash/io_win32.c @@ -87,9 +87,9 @@ bool ethash_file_size(FILE* f, size_t* ret_size) bool ethash_get_default_dirname(char* strbuf, size_t buffsize) { - static const char dir_suffix[] = "Ethash\\"; + static const char dir_suffix[] = "AppData\\Ethash\\"; strbuf[0] = '\0'; - if (!SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, (CHAR*)strbuf))) { + if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, (WCHAR*)strbuf))) { return false; } if (!ethash_strncat(strbuf, buffsize, "\\", 1)) { From 3bd7b5241c7b940102c939476a713971aaea2687 Mon Sep 17 00:00:00 2001 From: subtly Date: Mon, 18 May 2015 18:12:55 +0200 Subject: [PATCH 136/157] reverse ethash changes --- libethash/io_posix.c | 2 +- libethash/io_win32.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libethash/io_posix.c b/libethash/io_posix.c index 80046252d..1dea66ed1 100644 --- a/libethash/io_posix.c +++ b/libethash/io_posix.c @@ -89,7 +89,7 @@ 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; diff --git a/libethash/io_win32.c b/libethash/io_win32.c index e6e332b9f..2e6c8deb8 100644 --- a/libethash/io_win32.c +++ b/libethash/io_win32.c @@ -87,7 +87,7 @@ bool ethash_file_size(FILE* f, size_t* ret_size) bool ethash_get_default_dirname(char* strbuf, size_t buffsize) { - static const char dir_suffix[] = "AppData\\Ethash\\"; + static const char dir_suffix[] = "Appdata\\Ethash\\"; strbuf[0] = '\0'; if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, (WCHAR*)strbuf))) { return false; From 3b233f46e0d37323d2efdb0bb0437d2b1d603b8d Mon Sep 17 00:00:00 2001 From: subtly Date: Mon, 18 May 2015 18:13:52 +0200 Subject: [PATCH 137/157] reverse ethash changes --- libethash/io_posix.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libethash/io_posix.c b/libethash/io_posix.c index 1dea66ed1..7f03d5482 100644 --- a/libethash/io_posix.c +++ b/libethash/io_posix.c @@ -89,7 +89,6 @@ 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; From dd8bc4b78d30a97536001ab8fd37c7b1ac194b04 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 18 May 2015 21:00:21 +0200 Subject: [PATCH 138/157] Parallelised uncle checking. --- ethminer/MinerAux.h | 4 ++-- libethcore/Common.h | 5 +++-- libethereum/BlockChain.cpp | 4 ++-- libethereum/BlockQueue.cpp | 3 +++ libethereum/State.cpp | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 31e66d94a..ee78dc1c2 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -362,7 +362,7 @@ private: cout << "inner mean: " << innerMean << " H/s" << endl; (void)_phoneHome; - #if ETH_JSONRPC || !ETH_TRUE +#if ETH_JSONRPC || !ETH_TRUE if (_phoneHome) { cout << "Phoning home to find world ranking..." << endl; @@ -378,7 +378,7 @@ private: cout << "Error phoning home. ET is sad." << endl; } } - #endif +#endif exit(0); } diff --git a/libethcore/Common.h b/libethcore/Common.h index 8855bc3a7..2cb505905 100644 --- a/libethcore/Common.h +++ b/libethcore/Common.h @@ -100,9 +100,10 @@ struct ImportRequirements using value = unsigned; enum { - ValidNonce = 1, ///< Validate Nonce + ValidNonce = 1, ///< Validate nonce DontHave = 2, ///< Avoid old blocks - Default = ValidNonce | DontHave + CheckUncles = 4, ///< Check uncle nonces + Default = ValidNonce | DontHave | CheckUncles }; }; diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index f4a1dcec2..73747b25b 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -317,8 +317,8 @@ tuple BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st { try { - // Nonce is already verified thread at this point. - auto r = import(block.first, block.second, _stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce); + // Nonce & uncle nonces already verified thread at this point. + auto r = import(block.first, block.second, _stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce & ~ImportRequirements::CheckUncles); fresh += r.first; dead += r.second; } diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index df134b246..2af95d00c 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -78,6 +78,9 @@ void BlockQueue::verifierBody() try { res.first.populate(res.second, CheckEverything, work.first); res.first.verifyInternals(&res.second); + RLP r(&res.second); + for (auto const& uncle: r[2]) + BlockInfo().populateFromHeader(RLP(uncle.data()), CheckEverything); } catch (...) { diff --git a/libethereum/State.cpp b/libethereum/State.cpp index b9e548ea3..3bf7aaff7 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -667,7 +667,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement BOOST_THROW_EXCEPTION(UncleInChain() << errinfo_comment("Uncle in block already mentioned") << errinfo_data(toString(excluded)) << errinfo_hash256(sha3(i.data()))); excluded.insert(h); - BlockInfo uncle = BlockInfo::fromHeader(i.data(), CheckEverything, h); + BlockInfo uncle = BlockInfo::fromHeader(i.data(), (_ir & ImportRequirements::CheckUncles) ? CheckEverything : IgnoreNonce, h); BlockInfo uncleParent(_bc.block(uncle.parentHash)); if ((bigint)uncleParent.number < (bigint)m_currentBlock.number - 7) BOOST_THROW_EXCEPTION(UncleTooOld()); From f55975b5dcffd0ebda49fe63eafdc450df486d40 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Tue, 19 May 2015 09:12:15 +0200 Subject: [PATCH 139/157] cleaner output --- libethereum/Client.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 6d5e39e39..30eb12352 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -606,9 +606,10 @@ bool Client::remoteActive() const void Client::onPostStateChanged() { - cnote << "Post state changed: Restarting mining..."; + cnote << "Post state changed"; if (isMining() || remoteActive()) { + cnote << "Restarting mining..."; DEV_WRITE_GUARDED(x_working) m_working.commitToMine(m_bc); DEV_READ_GUARDED(x_working) From 996d340d493360ad0a1c4c635b0ae800357fff97 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 19 May 2015 11:26:52 +0200 Subject: [PATCH 140/157] remove JavaScript ownership --- mix/CodeModel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix/CodeModel.h b/mix/CodeModel.h index 95c44febe..994e9936a 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -157,7 +157,7 @@ class GasMap: public QObject Q_PROPERTY(bool isInfinite MEMBER m_isInfinite CONSTANT) public: - GasMap(int _start, int _end, QString _gas, bool _isInfinite, QObject* _parent): QObject(_parent), m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } + GasMap(int _start, int _end, QString _gas, bool _isInfinite, QObject* _parent): QObject(_parent), m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite) {} int m_start; int m_end; From e19ac5054c6331ffcec05e553087409d9235c53b Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 18 May 2015 22:14:03 +0200 Subject: [PATCH 141/157] use TrieHash for transactions and receipts roots --- libdevcore/Common.h | 3 +- libdevcore/CommonData.cpp | 12 ++++++++ libdevcore/CommonData.h | 1 + libdevcrypto/TrieHash.cpp | 29 +++++++++++-------- libdevcrypto/TrieHash.h | 5 ++-- libethereum/State.cpp | 20 ++++--------- test/libdevcrypto/trie.cpp | 57 ++++++++++++++++++++++++-------------- 7 files changed, 76 insertions(+), 51 deletions(-) diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 95817e41c..240746302 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -86,8 +86,9 @@ extern const u256 UndefinedU256; // Map types. using StringMap = std::map; +using BytesMap = std::map; using u256Map = std::map; -using HexMap = std::map; +using HexMap = std::map; // Hash types. using StringHashMap = std::unordered_map; diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp index 6cad29952..ba2b412fd 100644 --- a/libdevcore/CommonData.cpp +++ b/libdevcore/CommonData.cpp @@ -115,6 +115,18 @@ bytes dev::fromHex(std::string const& _s, WhenError _throw) return ret; } +bytes dev::asNibbles(bytes const& _s) +{ + std::vector ret; + ret.reserve(_s.size() * 2); + for (auto i: _s) + { + ret.push_back(i / 16); + ret.push_back(i % 16); + } + return ret; +} + bytes dev::asNibbles(std::string const& _s) { std::vector ret; diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h index 6c1f34667..29cc8e7c7 100644 --- a/libdevcore/CommonData.h +++ b/libdevcore/CommonData.h @@ -96,6 +96,7 @@ inline bytes asBytes(std::string const& _b) /// Converts a string into the big-endian base-16 stream of integers (NOT ASCII). /// @example asNibbles("A")[0] == 4 && asNibbles("A")[1] == 1 bytes asNibbles(std::string const& _s); +bytes asNibbles(bytes const& _s); // Big-endian to/from host endian conversion functions. diff --git a/libdevcrypto/TrieHash.cpp b/libdevcrypto/TrieHash.cpp index 0b02ce77f..4c4ca620d 100644 --- a/libdevcrypto/TrieHash.cpp +++ b/libdevcrypto/TrieHash.cpp @@ -158,43 +158,48 @@ void hash256aux(HexMap const& _s, HexMap::const_iterator _begin, HexMap::const_i } } -h256 hash256(StringMap const& _s) +bytes rlp256(BytesMap const& _s) { // build patricia tree. if (_s.empty()) - return sha3(rlp("")); + return rlp(""); HexMap hexMap; for (auto i = _s.rbegin(); i != _s.rend(); ++i) hexMap[asNibbles(i->first)] = i->second; RLPStream s; hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s); - return sha3(s.out()); + return s.out(); } -bytes rlp256(StringMap const& _s) +h256 hash256(BytesMap const& _s) +{ + return sha3(rlp256(_s)); +} + +h256 hash256(StringMap const& _s) { // build patricia tree. if (_s.empty()) - return rlp(""); + return sha3(rlp("")); HexMap hexMap; for (auto i = _s.rbegin(); i != _s.rend(); ++i) - hexMap[asNibbles(i->first)] = i->second; + hexMap[asNibbles(i->first)] = bytes(i->second.begin(), i->second.end()); RLPStream s; - hash256aux(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s); - return s.out(); + hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s); + return sha3(s.out()); } -h256 hash256(u256Map const& _s) +bytes rlp256(StringMap const& _s) { // build patricia tree. if (_s.empty()) - return sha3(rlp("")); + return rlp(""); HexMap hexMap; for (auto i = _s.rbegin(); i != _s.rend(); ++i) - hexMap[asNibbles(toBigEndianString(i->first))] = asString(rlp(i->second)); + hexMap[asNibbles(i->first)] = bytes(i->second.begin(), i->second.end()); RLPStream s; hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s); - return sha3(s.out()); + return s.out(); } /*h256 orderedTrieRoot(std::vector const& _data) diff --git a/libdevcrypto/TrieHash.h b/libdevcrypto/TrieHash.h index b0588fc38..46f9b1efb 100644 --- a/libdevcrypto/TrieHash.h +++ b/libdevcrypto/TrieHash.h @@ -27,9 +27,10 @@ namespace dev { +bytes rlp256(BytesMap const& _s); +h256 hash256(BytesMap const& _s); bytes rlp256(StringMap const& _s); h256 hash256(StringMap const& _s); -h256 hash256(u256Map const& _s); /*h256 orderedTrieRoot(std::vector const& _data); @@ -41,8 +42,6 @@ template inline h256 trieRootOver(unsigned _itemCount, T cons return hash256(m); }*/ -using bytesMap = std::unordered_map; - h256 orderedTrieRoot(std::vector const& _data); h256 orderedTrieRoot(std::vector const& _data); diff --git a/libethereum/State.cpp b/libethereum/State.cpp index b9e548ea3..d586941b4 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -840,16 +840,8 @@ void State::commitToMine(BlockChain const& _bc) } } - // TODO: move over to using TrieHash - - - MemoryDB tm; - GenericTrieDB transactionsTrie(&tm); - transactionsTrie.init(); - - MemoryDB rm; - GenericTrieDB receiptsTrie(&rm); - receiptsTrie.init(); + BytesMap transactionsMap; + BytesMap receiptsMap; RLPStream txs; txs.appendList(m_transactions.size()); @@ -861,11 +853,11 @@ void State::commitToMine(BlockChain const& _bc) RLPStream receiptrlp; m_receipts[i].streamRLP(receiptrlp); - receiptsTrie.insert(&k.out(), &receiptrlp.out()); + receiptsMap.insert(std::make_pair(k.out(), receiptrlp.out())); RLPStream txrlp; m_transactions[i].streamRLP(txrlp); - transactionsTrie.insert(&k.out(), &txrlp.out()); + transactionsMap.insert(std::make_pair(k.out(), txrlp.out())); txs.appendRaw(txrlp.out()); } @@ -874,8 +866,8 @@ void State::commitToMine(BlockChain const& _bc) RLPStream(unclesCount).appendRaw(unclesData.out(), unclesCount).swapOut(m_currentUncles); - m_currentBlock.transactionsRoot = transactionsTrie.root(); - m_currentBlock.receiptsRoot = receiptsTrie.root(); + m_currentBlock.transactionsRoot = hash256(transactionsMap); + m_currentBlock.receiptsRoot = hash256(receiptsMap); m_currentBlock.logBloom = logBloom(); m_currentBlock.sha3Uncles = sha3(m_currentUncles); diff --git a/test/libdevcrypto/trie.cpp b/test/libdevcrypto/trie.cpp index ecfc515aa..00bccd241 100644 --- a/test/libdevcrypto/trie.cpp +++ b/test/libdevcrypto/trie.cpp @@ -294,15 +294,27 @@ BOOST_AUTO_TEST_CASE(trie_tests_ordered) } } -inline h256 stringMapHash256(StringMap const& _s) +h256 stringMapHash256(StringMap const& _s) { - return hash256(_s); + //return hash256(_s); + BytesMap bytesMap; + for (auto const& _v: _s) + bytesMap.insert(std::make_pair(bytes(_v.first.begin(), _v.first.end()), bytes(_v.second.begin(), _v.second.end()))); + return hash256(bytesMap); +} + +bytes stringMapRlp256(StringMap const& _s) +{ + //return rlp256(_s); + BytesMap bytesMap; + for (auto const& _v: _s) + bytesMap.insert(std::make_pair(bytes(_v.first.begin(), _v.first.end()), bytes(_v.second.begin(), _v.second.end()))); + return rlp256(bytesMap); } BOOST_AUTO_TEST_CASE(moreTrieTests) { cnote << "Testing Trie more..."; -#if 0 // More tests... { MemoryDB m; @@ -311,7 +323,7 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) cout << t; cout << m; cout << t.root() << endl; - cout << hash256(StringMap()) << endl; + cout << stringMapHash256(StringMap()) << endl; t.insert(string("tesz"), string("test")); cout << t; @@ -336,7 +348,7 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) t.remove(string("test")); cout << m; cout << t.root() << endl; - cout << hash256(StringMap()) << endl; + cout << stringMapHash256(StringMap()) << endl; } { MemoryDB m; @@ -348,20 +360,23 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) cout << m; cout << t.root() << endl; cout << stringMapHash256({{"b", "B"}, {"a", "A"}}) << endl; - cout << RLP(rlp256({{"b", "B"}, {"a", "A"}})) << endl; + bytes r(stringMapRlp256({{"b", "B"}, {"a", "A"}})); + cout << RLP(r) << endl; } { MemTrie t; t.insert("dog", "puppy"); cout << hex << t.hash256() << endl; - cout << RLP(t.rlp()) << endl; + bytes r(t.rlp()); + cout << RLP(r) << endl; } { MemTrie t; t.insert("bed", "d"); t.insert("be", "e"); cout << hex << t.hash256() << endl; - cout << RLP(t.rlp()) << endl; + bytes r(t.rlp()); + cout << RLP(r) << endl; } { cout << hex << stringMapHash256({{"dog", "puppy"}, {"doe", "reindeer"}}) << endl; @@ -369,10 +384,10 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) t.insert("dog", "puppy"); t.insert("doe", "reindeer"); cout << hex << t.hash256() << endl; - cout << RLP(t.rlp()) << endl; + bytes r(t.rlp()); + cout << RLP(r) << endl; cout << toHex(t.rlp()) << endl; } -#endif { MemoryDB m; EnforceRefs r(m, true); @@ -387,16 +402,17 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) t.insert(a, b); s[a] = b; - /*cout << endl << "-------------------------------" << endl; + cout << endl << "-------------------------------" << endl; cout << a << " -> " << b << endl; cout << d; cout << m; cout << d.root() << endl; - cout << hash256(s) << endl;*/ + cout << hash256(s) << endl; + cout << stringMapHash256(s) << endl; BOOST_REQUIRE(d.check(true)); - BOOST_REQUIRE_EQUAL(t.hash256(), hash256(s)); - BOOST_REQUIRE_EQUAL(d.root(), hash256(s)); + BOOST_REQUIRE_EQUAL(t.hash256(), stringMapHash256(s)); + BOOST_REQUIRE_EQUAL(d.root(), stringMapHash256(s)); for (auto const& i: s) { (void)i; @@ -421,8 +437,8 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) BOOST_REQUIRE(d.check(true)); BOOST_REQUIRE(t.at(a).empty()); BOOST_REQUIRE(d.at(string(a)).empty()); - BOOST_REQUIRE_EQUAL(t.hash256(), hash256(s)); - BOOST_REQUIRE_EQUAL(d.root(), hash256(s)); + BOOST_REQUIRE_EQUAL(t.hash256(), stringMapHash256(s)); + BOOST_REQUIRE_EQUAL(d.root(), stringMapHash256(s)); for (auto const& i: s) { (void)i; @@ -493,7 +509,6 @@ BOOST_AUTO_TEST_CASE(trieLowerBound) BOOST_AUTO_TEST_CASE(trieStess) { cnote << "Stress-testing Trie..."; - if (0) { MemoryDB m; MemoryDB dm; @@ -512,8 +527,8 @@ BOOST_AUTO_TEST_CASE(trieStess) m[k] = v; t.insert(k, v); d.insert(k, v); - BOOST_REQUIRE_EQUAL(hash256(m), t.hash256()); - BOOST_REQUIRE_EQUAL(hash256(m), d.root()); + BOOST_REQUIRE_EQUAL(stringMapHash256(m), t.hash256()); + BOOST_REQUIRE_EQUAL(stringMapHash256(m), d.root()); BOOST_REQUIRE(d.check(true)); } while (!m.empty()) @@ -557,8 +572,8 @@ BOOST_AUTO_TEST_CASE(trieStess) cwarn << "Good?" << d2.root(); } BOOST_REQUIRE(d.check(true)); - BOOST_REQUIRE_EQUAL(hash256(m), t.hash256()); - BOOST_REQUIRE_EQUAL(hash256(m), d.root()); + BOOST_REQUIRE_EQUAL(stringMapHash256(m), t.hash256()); + BOOST_REQUIRE_EQUAL(stringMapHash256(m), d.root()); } } } From 4e358001acd9f478d2e69b16794cec4832afb1fa Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 19 May 2015 10:39:33 +0200 Subject: [PATCH 142/157] orderedTrieRoot testing --- libdevcore/CommonData.cpp | 14 +--------- libdevcore/CommonData.h | 3 +-- libdevcrypto/TrieHash.cpp | 55 ++++++-------------------------------- libdevcrypto/TrieHash.h | 10 +++---- libethcore/BlockInfo.cpp | 12 +-------- test/libdevcrypto/trie.cpp | 3 --- 6 files changed, 15 insertions(+), 82 deletions(-) diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp index ba2b412fd..f8d8c172f 100644 --- a/libdevcore/CommonData.cpp +++ b/libdevcore/CommonData.cpp @@ -115,19 +115,7 @@ bytes dev::fromHex(std::string const& _s, WhenError _throw) return ret; } -bytes dev::asNibbles(bytes const& _s) -{ - std::vector ret; - ret.reserve(_s.size() * 2); - for (auto i: _s) - { - ret.push_back(i / 16); - ret.push_back(i % 16); - } - return ret; -} - -bytes dev::asNibbles(std::string const& _s) +bytes dev::asNibbles(bytesConstRef const& _s) { std::vector ret; ret.reserve(_s.size() * 2); diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h index 29cc8e7c7..702f1f808 100644 --- a/libdevcore/CommonData.h +++ b/libdevcore/CommonData.h @@ -95,8 +95,7 @@ inline bytes asBytes(std::string const& _b) /// Converts a string into the big-endian base-16 stream of integers (NOT ASCII). /// @example asNibbles("A")[0] == 4 && asNibbles("A")[1] == 1 -bytes asNibbles(std::string const& _s); -bytes asNibbles(bytes const& _s); +bytes asNibbles(bytesConstRef const& _s); // Big-endian to/from host endian conversion functions. diff --git a/libdevcrypto/TrieHash.cpp b/libdevcrypto/TrieHash.cpp index 4c4ca620d..0f2d68b91 100644 --- a/libdevcrypto/TrieHash.cpp +++ b/libdevcrypto/TrieHash.cpp @@ -165,7 +165,7 @@ bytes rlp256(BytesMap const& _s) return rlp(""); HexMap hexMap; for (auto i = _s.rbegin(); i != _s.rend(); ++i) - hexMap[asNibbles(i->first)] = i->second; + hexMap[asNibbles(bytesConstRef(&i->first))] = i->second; RLPStream s; hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s); return s.out(); @@ -176,61 +176,22 @@ h256 hash256(BytesMap const& _s) return sha3(rlp256(_s)); } -h256 hash256(StringMap const& _s) -{ - // build patricia tree. - if (_s.empty()) - return sha3(rlp("")); - HexMap hexMap; - for (auto i = _s.rbegin(); i != _s.rend(); ++i) - hexMap[asNibbles(i->first)] = bytes(i->second.begin(), i->second.end()); - RLPStream s; - hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s); - return sha3(s.out()); -} - -bytes rlp256(StringMap const& _s) -{ - // build patricia tree. - if (_s.empty()) - return rlp(""); - HexMap hexMap; - for (auto i = _s.rbegin(); i != _s.rend(); ++i) - hexMap[asNibbles(i->first)] = bytes(i->second.begin(), i->second.end()); - RLPStream s; - hash256rlp(hexMap, hexMap.cbegin(), hexMap.cend(), 0, s); - return s.out(); -} - -/*h256 orderedTrieRoot(std::vector const& _data) +h256 orderedTrieRoot(std::vector const& _data) { - StringMap m; + BytesMap m; unsigned j = 0; for (auto i: _data) - m[asString(rlp(j++))] = asString(i); + m[rlp(j++)] = i; return hash256(m); -}*/ - -h256 orderedTrieRoot(std::vector const& _data) -{ - MemoryDB db; - GenericTrieDB t(&db); - t.init(); - unsigned j = 0; - for (auto i: _data) - t.insert(rlp(j++), i.toBytes()); - return t.root(); } -h256 orderedTrieRoot(std::vector const& _data) +h256 orderedTrieRoot(std::vector const& _data) { - MemoryDB db; - GenericTrieDB t(&db); - t.init(); + BytesMap m; unsigned j = 0; for (auto i: _data) - t.insert(rlp(j++), i); - return t.root(); + m[rlp(j++)] = i.toBytes(); + return hash256(m); } } diff --git a/libdevcrypto/TrieHash.h b/libdevcrypto/TrieHash.h index 46f9b1efb..9649ef0c7 100644 --- a/libdevcrypto/TrieHash.h +++ b/libdevcrypto/TrieHash.h @@ -29,18 +29,16 @@ namespace dev bytes rlp256(BytesMap const& _s); h256 hash256(BytesMap const& _s); -bytes rlp256(StringMap const& _s); -h256 hash256(StringMap const& _s); -/*h256 orderedTrieRoot(std::vector const& _data); +h256 orderedTrieRoot(std::vector const& _data); template inline h256 trieRootOver(unsigned _itemCount, T const& _getKey, U const& _getValue) { - StringMap m; + BytesMap m; for (unsigned i = 0; i < _itemCount; ++i) - m[asString(_getKey(i))] = asString(_getValue(i)); + m[_getKey(i)] = _getValue(i); return hash256(m); -}*/ +} h256 orderedTrieRoot(std::vector const& _data); h256 orderedTrieRoot(std::vector const& _data); diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index 00a5108c4..0c324d70f 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -191,22 +191,12 @@ void BlockInfo::populate(bytesConstRef _block, Strictness _s, h256 const& _h) struct BlockInfoDiagnosticsChannel: public LogChannel { static const char* name() { return EthBlue "▧" EthWhite " ◌"; } static const int verbosity = 9; }; -template h256 trieRootOver(unsigned _itemCount, T const& _getKey, U const& _getValue) -{ - MemoryDB db; - GenericTrieDB t(&db); - t.init(); - for (unsigned i = 0; i < _itemCount; ++i) - t.insert(_getKey(i), _getValue(i)); - return t.root(); -} - void BlockInfo::verifyInternals(bytesConstRef _block) const { RLP root(_block); auto txList = root[1]; - auto expectedRoot = trieRootOver(txList.itemCount(), [&](unsigned i){ return rlp(i); }, [&](unsigned i){ return txList[i].data(); }); + auto expectedRoot = trieRootOver(txList.itemCount(), [&](unsigned i){ return rlp(i); }, [&](unsigned i){ return txList[i].data().toBytes(); }); clog(BlockInfoDiagnosticsChannel) << "Expected trie root:" << toString(expectedRoot); if (transactionsRoot != expectedRoot) diff --git a/test/libdevcrypto/trie.cpp b/test/libdevcrypto/trie.cpp index 00bccd241..b32fd70e1 100644 --- a/test/libdevcrypto/trie.cpp +++ b/test/libdevcrypto/trie.cpp @@ -296,7 +296,6 @@ BOOST_AUTO_TEST_CASE(trie_tests_ordered) h256 stringMapHash256(StringMap const& _s) { - //return hash256(_s); BytesMap bytesMap; for (auto const& _v: _s) bytesMap.insert(std::make_pair(bytes(_v.first.begin(), _v.first.end()), bytes(_v.second.begin(), _v.second.end()))); @@ -305,7 +304,6 @@ h256 stringMapHash256(StringMap const& _s) bytes stringMapRlp256(StringMap const& _s) { - //return rlp256(_s); BytesMap bytesMap; for (auto const& _v: _s) bytesMap.insert(std::make_pair(bytes(_v.first.begin(), _v.first.end()), bytes(_v.second.begin(), _v.second.end()))); @@ -407,7 +405,6 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) cout << d; cout << m; cout << d.root() << endl; - cout << hash256(s) << endl; cout << stringMapHash256(s) << endl; BOOST_REQUIRE(d.check(true)); From c8c22fcfbd8afb8ebb3a4f19ba1f5503d354b6a6 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 19 May 2015 13:17:13 +0200 Subject: [PATCH 143/157] Fixed 1970 More frequent chain updates. --- libethereum/Client.cpp | 2 +- libweb3jsonrpc/WebThreeStubServerBase.cpp | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 6d5e39e39..c46142fbb 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -484,7 +484,7 @@ void Client::syncBlockQueue() cwork << "BQ ==> CHAIN ==> STATE"; { - tie(ir.first, ir.second, m_syncBlockQueue) = m_bc.sync(m_bq, m_stateDB, 100); + tie(ir.first, ir.second, m_syncBlockQueue) = m_bc.sync(m_bq, m_stateDB, 10); if (ir.first.empty()) return; } diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index cac634a61..6b714f2ac 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -99,11 +99,12 @@ static Json::Value toJson(dev::eth::Transaction const& _t, std::pair(_blockHash); if (_includeTransactions) - return toJson(client()->blockInfo(h), client()->uncleHashes(h), client()->transactions(h)); + return toJson(client()->blockInfo(h), client()->blockDetails(h), client()->uncleHashes(h), client()->transactions(h)); else - return toJson(client()->blockInfo(h), client()->uncleHashes(h), client()->transactionHashes(h)); + return toJson(client()->blockInfo(h), client()->blockDetails(h), client()->uncleHashes(h), client()->transactionHashes(h)); } catch (...) { @@ -618,9 +620,9 @@ Json::Value WebThreeStubServerBase::eth_getBlockByNumber(string const& _blockNum { auto h = jsToBlockNumber(_blockNumber); if (_includeTransactions) - return toJson(client()->blockInfo(h), client()->uncleHashes(h), client()->transactions(h)); + return toJson(client()->blockInfo(h), client()->blockDetails(h), client()->uncleHashes(h), client()->transactions(h)); else - return toJson(client()->blockInfo(h), client()->uncleHashes(h), client()->transactionHashes(h)); + return toJson(client()->blockInfo(h), client()->blockDetails(h), client()->uncleHashes(h), client()->transactionHashes(h)); } catch (...) { From 1a334221eab18ed3a40de80196b0756a9848120f Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 19 May 2015 14:23:28 +0200 Subject: [PATCH 144/157] removed unused module --- mix/qml/Debugger.qml | 1 - mix/qml/StatesComboBox.qml | 1 - mix/qml/StatusPane.qml | 1 - 3 files changed, 3 deletions(-) diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index c6283b60e..9decc91ae 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -4,7 +4,6 @@ import QtQuick.Controls.Styles 1.1 import QtQuick.Dialogs 1.1 import QtQuick.Layouts 1.1 import Qt.labs.settings 1.0 -import QtGraphicalEffects 1.0 import "js/Debugger.js" as Debugger import "js/ErrorLocationFormater.js" as ErrorLocationFormater import "." diff --git a/mix/qml/StatesComboBox.qml b/mix/qml/StatesComboBox.qml index 907580ee7..3d2b08eef 100644 --- a/mix/qml/StatesComboBox.qml +++ b/mix/qml/StatesComboBox.qml @@ -23,7 +23,6 @@ import QtQuick 2.0 import QtQuick.Controls 1.0 import QtQuick.Layouts 1.1 -import QtGraphicalEffects 1.0 import org.ethereum.qml.InverseMouseArea 1.0 Rectangle { diff --git a/mix/qml/StatusPane.qml b/mix/qml/StatusPane.qml index 0c01caeb1..1c1453002 100644 --- a/mix/qml/StatusPane.qml +++ b/mix/qml/StatusPane.qml @@ -3,7 +3,6 @@ import QtQuick.Controls 1.1 import QtQuick.Layouts 1.1 import QtQuick.Controls.Styles 1.3 import org.ethereum.qml.InverseMouseArea 1.0 -import QtGraphicalEffects 1.0 import "js/ErrorLocationFormater.js" as ErrorLocationFormater import "." From 5f849c8eed8ce07fe5332df7349c3d2b6af07f5c Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 19 May 2015 15:18:04 +0200 Subject: [PATCH 145/157] Fix DownloadView Race condition - There is a race condition with potential division by zero which is mostly observed when debugging AZ from gdb where there is a big gap between window refreshes due to breakpoints and such --- alethzero/DownloadView.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp index 009e2dc83..210649edb 100644 --- a/alethzero/DownloadView.cpp +++ b/alethzero/DownloadView.cpp @@ -52,7 +52,10 @@ void DownloadView::paintEvent(QPaintEvent*) QPointF pos(0, 0); auto bg = m_man->blocksGot(); - + unsigned subCount = m_man->subCount(); + if (subCount == 0) + return; + unsigned dh = 360 / subCount; for (unsigned i = bg.all().first, ei = bg.all().second; i < ei; ++i) { int s = -2; @@ -68,7 +71,6 @@ void DownloadView::paintEvent(QPaintEvent*) h++; }); } - unsigned dh = 360 / m_man->subCount(); if (s == -2) p.fillRect(QRectF(QPointF(pos) + QPointF(3 * area.width() / 8, 3 * area.height() / 8), area / 4), Qt::black); else if (s == -1) From cbdb46ea435c34485f178f7d9a77ee59a75d8db9 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 19 May 2015 15:56:56 +0200 Subject: [PATCH 146/157] Miner fix. Possible fix for VM (and remove gas from the interface). --- libethash-cl/ethash_cl_miner.cpp | 15 ++++++++------- libethcore/Ethash.cpp | 4 ++-- libethereum/KeyManager.cpp | 4 ++++ libevm/SmartVM.h | 6 +++++- libevm/VM.cpp | 14 +++++++++----- libevm/VM.h | 8 +++++--- libevm/VMFace.h | 9 +++------ 7 files changed, 36 insertions(+), 24 deletions(-) diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp index 3891f2ef6..be17ba449 100644 --- a/libethash-cl/ethash_cl_miner.cpp +++ b/libethash-cl/ethash_cl_miner.cpp @@ -206,14 +206,15 @@ bool ethash_cl_miner::init(uint8_t const* _dag, uint64_t _dagSize, unsigned work m_header = cl::Buffer(m_context, CL_MEM_READ_ONLY, 32); // compute dag on CPU - { + try { m_queue.enqueueWriteBuffer(m_dag, CL_TRUE, 0, _dagSize, _dag); - - // if this throws then it's because we probably need to subdivide the dag uploads for compatibility -// void* dag_ptr = m_queue.enqueueMapBuffer(m_dag, true, m_opencl_1_1 ? CL_MAP_WRITE : CL_MAP_WRITE_INVALIDATE_REGION, 0, _dagSize); - // memcpying 1GB: horrible... really. horrible. but necessary since we can't mmap *and* gpumap. -// _fillDAG(dag_ptr); -// m_queue.enqueueUnmapMemObject(m_dag, dag_ptr); + } + catch (...) + { + // didn't work. shitty driver. try allocating in CPU RAM and manually memcpying it. + void* dag_ptr = m_queue.enqueueMapBuffer(m_dag, true, m_opencl_1_1 ? CL_MAP_WRITE : CL_MAP_WRITE_INVALIDATE_REGION, 0, _dagSize); + memcpy(dag_ptr, _dag, _dagSize); + m_queue.enqueueUnmapMemObject(m_dag, dag_ptr); } // create mining buffers diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 7609d8b6b..6276dd0a1 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -333,9 +333,9 @@ void Ethash::GPUMiner::workLoop() uint64_t upper64OfBoundary = (uint64_t)(u64)((u256)w.boundary >> 192); m_miner->search(w.headerHash.data(), upper64OfBoundary, *m_hook); } - catch (...) + catch (cl::Error const& _e) { - cwarn << "Error GPU mining. GPU memory fragmentation?"; + cwarn << "Error GPU mining: " << _e.what() << "(" << _e.err() << ")"; } } diff --git a/libethereum/KeyManager.cpp b/libethereum/KeyManager.cpp index 11b2cb2a6..cba6f4325 100644 --- a/libethereum/KeyManager.cpp +++ b/libethereum/KeyManager.cpp @@ -61,7 +61,11 @@ bool KeyManager::load(std::string const& _pass) 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]); + cdebug << toString((Address)i[0]) << toString((h128)i[1]) << toString((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]; diff --git a/libevm/SmartVM.h b/libevm/SmartVM.h index 29f464ecd..e21af23b0 100644 --- a/libevm/SmartVM.h +++ b/libevm/SmartVM.h @@ -31,12 +31,16 @@ namespace eth class SmartVM: public VMFace { public: - SmartVM(u256 _gas): VMFace(_gas) {} + SmartVM(u256 const& _gas): m_gas(_gas) {} virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final; + void reset(u256 const& _gas = 0) noexcept override { m_gas = _gas; } + u256 gas() const noexcept override { return (u256)m_gas; } + private: std::unique_ptr m_selectedVM; + bigint m_gas; }; } diff --git a/libevm/VM.cpp b/libevm/VM.cpp index 853ac25f6..368d27389 100644 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -25,9 +25,9 @@ using namespace std; using namespace dev; using namespace dev::eth; -void VM::reset(u256 _gas) noexcept +void VM::reset(u256 const& _gas) noexcept { - VMFace::reset(_gas); + m_gas = _gas; m_curPC = 0; m_jumpDests.clear(); } @@ -206,7 +206,7 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) BOOST_THROW_EXCEPTION(OutOfGas()); } - m_gas = (u256)((bigint)m_gas - runGas); + m_gas -= runGas; if (newTempSize > m_temp.size()) m_temp.resize((size_t)newTempSize); @@ -565,7 +565,7 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) m_stack.push_back(m_temp.size()); break; case Instruction::GAS: - m_stack.push_back(m_gas); + m_stack.push_back((u256)m_gas); break; case Instruction::JUMPDEST: break; @@ -614,7 +614,11 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) m_stack.pop_back(); if (_ext.balance(_ext.myAddress) >= endowment && _ext.depth < 1024) - m_stack.push_back((u160)_ext.create(endowment, m_gas, bytesConstRef(m_temp.data() + initOff, initSize), _onOp)); + { + u256 g(m_gas); + m_stack.push_back((u160)_ext.create(endowment, g, bytesConstRef(m_temp.data() + initOff, initSize), _onOp)); + m_gas = g; + } else m_stack.push_back(0); break; diff --git a/libevm/VM.h b/libevm/VM.h index 30007e0b3..668544f9d 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -52,8 +52,6 @@ inline u256 fromAddress(Address _a) class VM: public VMFace { public: - virtual void reset(u256 _gas = 0) noexcept override final; - virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final; void require(u256 _n, u256 _d) { if (m_stack.size() < _n) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(StackUnderflow() << RequirementError((bigint)_n, (bigint)m_stack.size())); } if (m_stack.size() - _n + _d > c_stackLimit) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(OutOfStack() << RequirementError((bigint)(_d - _n), (bigint)m_stack.size())); } } @@ -64,17 +62,21 @@ public: bytes const& memory() const { return m_temp; } u256s const& stack() const { return m_stack; } + void reset(u256 const& _gas = 0) noexcept override; + u256 gas() const noexcept override { return (u256)m_gas; } + private: friend class VMFactory; /// Construct VM object. - explicit VM(u256 _gas): VMFace(_gas) {} + explicit VM(u256 _gas): m_gas(_gas) {} u256 m_curPC = 0; bytes m_temp; u256s m_stack; std::set m_jumpDests; std::function m_onFail; + bigint m_gas = 0; }; } diff --git a/libevm/VMFace.h b/libevm/VMFace.h index d2689d13e..92e6d4c4f 100644 --- a/libevm/VMFace.h +++ b/libevm/VMFace.h @@ -38,18 +38,15 @@ struct StackUnderflow: virtual VMException {}; class VMFace { public: - explicit VMFace(u256 _gas): m_gas(_gas) {} + VMFace() = default; virtual ~VMFace() = default; VMFace(VMFace const&) = delete; VMFace& operator=(VMFace const&) = delete; - virtual void reset(u256 _gas = 0) noexcept { m_gas = _gas; } - u256 gas() const noexcept { return m_gas; } + virtual void reset(u256 const& _gas = 0) noexcept = 0; + virtual u256 gas() const noexcept = 0; virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) = 0; - -protected: - u256 m_gas = 0; }; } From 9adde95145acc8f097c828dc362e8c0f22a090c6 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 19 May 2015 19:38:17 +0200 Subject: [PATCH 147/157] SHA3, RIPEMD160 and SHA256 are now not cryptopp impls. --- libdevcrypto/AES.cpp | 32 +- libdevcrypto/AES.h | 5 +- libdevcrypto/Common.cpp | 1 + libdevcrypto/Hash.cpp | 440 ++++++++++++++++++++++ libdevcrypto/Hash.h | 38 ++ libdevcrypto/SHA3.cpp | 255 +++++++++---- libdevcrypto/SHA3.h | 37 +- libdevcrypto/picosha2.h | 360 ++++++++++++++++++ libethereum/Precompiled.cpp | 13 +- test/libdevcrypto/crypto.cpp | 14 +- test/libsolidity/SolidityEndToEndTest.cpp | 10 +- 11 files changed, 1075 insertions(+), 130 deletions(-) create mode 100644 libdevcrypto/Hash.cpp create mode 100644 libdevcrypto/Hash.h create mode 100644 libdevcrypto/picosha2.h diff --git a/libdevcrypto/AES.cpp b/libdevcrypto/AES.cpp index 56885ae36..e9edac0d3 100644 --- a/libdevcrypto/AES.cpp +++ b/libdevcrypto/AES.cpp @@ -19,9 +19,9 @@ * @date 2014 */ -#include "CryptoPP.h" #include "AES.h" - +#include +#include "CryptoPP.h" using namespace std; using namespace dev; using namespace dev::crypto; @@ -58,3 +58,31 @@ size_t Stream::streamOut(bytes&) return 0; } +bytes dev::aesDecrypt(bytesConstRef _ivCipher, std::string const& _password, unsigned _rounds, bytesConstRef _salt) +{ + bytes pw = asBytes(_password); + + if (!_salt.size()) + _salt = &pw; + + bytes target(64); + CryptoPP::PKCS5_PBKDF2_HMAC().DeriveKey(target.data(), target.size(), 0, pw.data(), pw.size(), _salt.data(), _salt.size(), _rounds); + + try + { + CryptoPP::AES::Decryption aesDecryption(target.data(), 16); + auto cipher = _ivCipher.cropped(16); + auto iv = _ivCipher.cropped(0, 16); + CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data()); + std::string decrypted; + CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(decrypted)); + stfDecryptor.Put(cipher.data(), cipher.size()); + stfDecryptor.MessageEnd(); + return asBytes(decrypted); + } + catch (exception const& e) + { + cerr << e.what() << endl; + return bytes(); + } +} diff --git a/libdevcrypto/AES.h b/libdevcrypto/AES.h index f0646eb85..32d1880dc 100644 --- a/libdevcrypto/AES.h +++ b/libdevcrypto/AES.h @@ -86,4 +86,7 @@ private: } } -} \ No newline at end of file + +bytes aesDecrypt(bytesConstRef _cipher, std::string const& _password, unsigned _rounds = 2000, bytesConstRef _salt = bytesConstRef()); + +} diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index a5c176fe6..52be6ce3b 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -27,6 +27,7 @@ #include #include #include "SHA3.h" +#include "AES.h" #include "FileSystem.h" #include "CryptoPP.h" using namespace std; diff --git a/libdevcrypto/Hash.cpp b/libdevcrypto/Hash.cpp new file mode 100644 index 000000000..c6b917b90 --- /dev/null +++ b/libdevcrypto/Hash.cpp @@ -0,0 +1,440 @@ +/* + 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 Hash.cpp + * @author Gav Wood + * @date 2014 + */ + +#include "Hash.h" +#include +#include +#include +#include "picosha2.h" +using namespace std; +using namespace dev; + +namespace dev +{ + +h256 sha256(bytesConstRef _input) +{ + h256 ret; + picosha2::hash256(_input.begin(), _input.end(), ret.data(), ret.data() + 32); + return ret; +} + +namespace rmd160 +{ + +/********************************************************************\ + * + * FILE: rmd160.h + * FILE: rmd160.c + * + * CONTENTS: Header file for a sample C-implementation of the + * RIPEMD-160 hash-function. + * TARGET: any computer with an ANSI C compiler + * + * AUTHOR: Antoon Bosselaers, ESAT-COSIC + * DATE: 1 March 1996 + * VERSION: 1.0 + * + * Copyright (c) Katholieke Universiteit Leuven + * 1996, All Rights Reserved + * + \********************************************************************/ + +// Adapted into "header-only" format by Gav Wood. + +/* macro definitions */ + +#define RMDsize 160 + +/* collect four bytes into one word: */ +#define BYTES_TO_DWORD(strptr) \ +(((uint32_t) *((strptr)+3) << 24) | \ +((uint32_t) *((strptr)+2) << 16) | \ +((uint32_t) *((strptr)+1) << 8) | \ +((uint32_t) *(strptr))) + +/* ROL(x, n) cyclically rotates x over n bits to the left */ +/* x must be of an unsigned 32 bits type and 0 <= n < 32. */ +#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* the five basic functions F(), G() and H() */ +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define J(x, y, z) ((x) ^ ((y) | ~(z))) + +/* the ten basic operations FF() through III() */ +#define FF(a, b, c, d, e, x, s) {\ +(a) += F((b), (c), (d)) + (x);\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define GG(a, b, c, d, e, x, s) {\ +(a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define HH(a, b, c, d, e, x, s) {\ +(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define II(a, b, c, d, e, x, s) {\ +(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define JJ(a, b, c, d, e, x, s) {\ +(a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define FFF(a, b, c, d, e, x, s) {\ +(a) += F((b), (c), (d)) + (x);\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define GGG(a, b, c, d, e, x, s) {\ +(a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define HHH(a, b, c, d, e, x, s) {\ +(a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define III(a, b, c, d, e, x, s) {\ +(a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} +#define JJJ(a, b, c, d, e, x, s) {\ +(a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ +(a) = ROL((a), (s)) + (e);\ +(c) = ROL((c), 10);\ +} + +void MDinit(uint32_t *MDbuf) +{ + MDbuf[0] = 0x67452301UL; + MDbuf[1] = 0xefcdab89UL; + MDbuf[2] = 0x98badcfeUL; + MDbuf[3] = 0x10325476UL; + MDbuf[4] = 0xc3d2e1f0UL; + + return; +} + +/********************************************************************/ + +void MDcompress(uint32_t *MDbuf, uint32_t *X) +{ + uint32_t aa = MDbuf[0], bb = MDbuf[1], cc = MDbuf[2], + dd = MDbuf[3], ee = MDbuf[4]; + uint32_t aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2], + ddd = MDbuf[3], eee = MDbuf[4]; + + /* round 1 */ + FF(aa, bb, cc, dd, ee, X[ 0], 11); + FF(ee, aa, bb, cc, dd, X[ 1], 14); + FF(dd, ee, aa, bb, cc, X[ 2], 15); + FF(cc, dd, ee, aa, bb, X[ 3], 12); + FF(bb, cc, dd, ee, aa, X[ 4], 5); + FF(aa, bb, cc, dd, ee, X[ 5], 8); + FF(ee, aa, bb, cc, dd, X[ 6], 7); + FF(dd, ee, aa, bb, cc, X[ 7], 9); + FF(cc, dd, ee, aa, bb, X[ 8], 11); + FF(bb, cc, dd, ee, aa, X[ 9], 13); + FF(aa, bb, cc, dd, ee, X[10], 14); + FF(ee, aa, bb, cc, dd, X[11], 15); + FF(dd, ee, aa, bb, cc, X[12], 6); + FF(cc, dd, ee, aa, bb, X[13], 7); + FF(bb, cc, dd, ee, aa, X[14], 9); + FF(aa, bb, cc, dd, ee, X[15], 8); + + /* round 2 */ + GG(ee, aa, bb, cc, dd, X[ 7], 7); + GG(dd, ee, aa, bb, cc, X[ 4], 6); + GG(cc, dd, ee, aa, bb, X[13], 8); + GG(bb, cc, dd, ee, aa, X[ 1], 13); + GG(aa, bb, cc, dd, ee, X[10], 11); + GG(ee, aa, bb, cc, dd, X[ 6], 9); + GG(dd, ee, aa, bb, cc, X[15], 7); + GG(cc, dd, ee, aa, bb, X[ 3], 15); + GG(bb, cc, dd, ee, aa, X[12], 7); + GG(aa, bb, cc, dd, ee, X[ 0], 12); + GG(ee, aa, bb, cc, dd, X[ 9], 15); + GG(dd, ee, aa, bb, cc, X[ 5], 9); + GG(cc, dd, ee, aa, bb, X[ 2], 11); + GG(bb, cc, dd, ee, aa, X[14], 7); + GG(aa, bb, cc, dd, ee, X[11], 13); + GG(ee, aa, bb, cc, dd, X[ 8], 12); + + /* round 3 */ + HH(dd, ee, aa, bb, cc, X[ 3], 11); + HH(cc, dd, ee, aa, bb, X[10], 13); + HH(bb, cc, dd, ee, aa, X[14], 6); + HH(aa, bb, cc, dd, ee, X[ 4], 7); + HH(ee, aa, bb, cc, dd, X[ 9], 14); + HH(dd, ee, aa, bb, cc, X[15], 9); + HH(cc, dd, ee, aa, bb, X[ 8], 13); + HH(bb, cc, dd, ee, aa, X[ 1], 15); + HH(aa, bb, cc, dd, ee, X[ 2], 14); + HH(ee, aa, bb, cc, dd, X[ 7], 8); + HH(dd, ee, aa, bb, cc, X[ 0], 13); + HH(cc, dd, ee, aa, bb, X[ 6], 6); + HH(bb, cc, dd, ee, aa, X[13], 5); + HH(aa, bb, cc, dd, ee, X[11], 12); + HH(ee, aa, bb, cc, dd, X[ 5], 7); + HH(dd, ee, aa, bb, cc, X[12], 5); + + /* round 4 */ + II(cc, dd, ee, aa, bb, X[ 1], 11); + II(bb, cc, dd, ee, aa, X[ 9], 12); + II(aa, bb, cc, dd, ee, X[11], 14); + II(ee, aa, bb, cc, dd, X[10], 15); + II(dd, ee, aa, bb, cc, X[ 0], 14); + II(cc, dd, ee, aa, bb, X[ 8], 15); + II(bb, cc, dd, ee, aa, X[12], 9); + II(aa, bb, cc, dd, ee, X[ 4], 8); + II(ee, aa, bb, cc, dd, X[13], 9); + II(dd, ee, aa, bb, cc, X[ 3], 14); + II(cc, dd, ee, aa, bb, X[ 7], 5); + II(bb, cc, dd, ee, aa, X[15], 6); + II(aa, bb, cc, dd, ee, X[14], 8); + II(ee, aa, bb, cc, dd, X[ 5], 6); + II(dd, ee, aa, bb, cc, X[ 6], 5); + II(cc, dd, ee, aa, bb, X[ 2], 12); + + /* round 5 */ + JJ(bb, cc, dd, ee, aa, X[ 4], 9); + JJ(aa, bb, cc, dd, ee, X[ 0], 15); + JJ(ee, aa, bb, cc, dd, X[ 5], 5); + JJ(dd, ee, aa, bb, cc, X[ 9], 11); + JJ(cc, dd, ee, aa, bb, X[ 7], 6); + JJ(bb, cc, dd, ee, aa, X[12], 8); + JJ(aa, bb, cc, dd, ee, X[ 2], 13); + JJ(ee, aa, bb, cc, dd, X[10], 12); + JJ(dd, ee, aa, bb, cc, X[14], 5); + JJ(cc, dd, ee, aa, bb, X[ 1], 12); + JJ(bb, cc, dd, ee, aa, X[ 3], 13); + JJ(aa, bb, cc, dd, ee, X[ 8], 14); + JJ(ee, aa, bb, cc, dd, X[11], 11); + JJ(dd, ee, aa, bb, cc, X[ 6], 8); + JJ(cc, dd, ee, aa, bb, X[15], 5); + JJ(bb, cc, dd, ee, aa, X[13], 6); + + /* parallel round 1 */ + JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); + JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); + JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); + JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); + JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); + JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); + JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); + JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); + + /* parallel round 2 */ + III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); + III(ddd, eee, aaa, bbb, ccc, X[11], 13); + III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); + III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); + III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); + III(eee, aaa, bbb, ccc, ddd, X[13], 8); + III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); + III(ccc, ddd, eee, aaa, bbb, X[10], 11); + III(bbb, ccc, ddd, eee, aaa, X[14], 7); + III(aaa, bbb, ccc, ddd, eee, X[15], 7); + III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); + III(ddd, eee, aaa, bbb, ccc, X[12], 7); + III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); + III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); + III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); + III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); + + /* parallel round 3 */ + HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); + HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); + HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); + HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); + HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); + HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); + HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); + HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); + HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); + HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); + HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); + HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); + HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); + HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); + HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); + HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); + + /* parallel round 4 */ + GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); + GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); + GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); + GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); + GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); + GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); + GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); + GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); + GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); + GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); + GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); + GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); + GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); + GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); + GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); + GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); + + /* parallel round 5 */ + FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); + FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); + FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); + FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); + FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); + FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); + FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); + FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); + FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); + FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); + FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); + FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); + FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); + FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); + + /* combine results */ + ddd += cc + MDbuf[1]; /* final result for MDbuf[0] */ + MDbuf[1] = MDbuf[2] + dd + eee; + MDbuf[2] = MDbuf[3] + ee + aaa; + MDbuf[3] = MDbuf[4] + aa + bbb; + MDbuf[4] = MDbuf[0] + bb + ccc; + MDbuf[0] = ddd; + + return; +} + +void MDfinish(uint32_t *MDbuf, byte const *strptr, uint32_t lswlen, uint32_t mswlen) +{ + unsigned int i; /* counter */ + uint32_t X[16]; /* message words */ + + memset(X, 0, 16*sizeof(uint32_t)); + + /* put bytes from strptr into X */ + for (i=0; i<(lswlen&63); i++) { + /* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */ + X[i>>2] ^= (uint32_t) *strptr++ << (8 * (i&3)); + } + + /* append the bit m_n == 1 */ + X[(lswlen>>2)&15] ^= (uint32_t)1 << (8*(lswlen&3) + 7); + + if ((lswlen & 63) > 55) { + /* length goes to next block */ + MDcompress(MDbuf, X); + memset(X, 0, 16*sizeof(uint32_t)); + } + + /* append length in bits*/ + X[14] = lswlen << 3; + X[15] = (lswlen >> 29) | (mswlen << 3); + MDcompress(MDbuf, X); + + return; +} + +#undef ROL +#undef F +#undef G +#undef H +#undef I +#undef J +#undef FF +#undef GG +#undef HH +#undef II +#undef JJ +#undef FFF +#undef GGG +#undef HHH +#undef III +#undef JJJ + +} + +/* + * @returns RMD(_input) + */ +h160 ripemd160(bytesConstRef _input) +{ + h160 hashcode; + uint32_t buffer[RMDsize / 32]; // contains (A, B, C, D(, E)) + uint32_t current[16]; // current 16-word chunk + + // initialize + rmd160::MDinit(buffer); + byte const* message = _input.data(); + uint32_t remaining = _input.size(); // # of bytes not yet processed + + // process message in 16x 4-byte chunks + for (; remaining >= 64; remaining -= 64) + { + for (unsigned i = 0; i < 16; i++) + { + current[i] = BYTES_TO_DWORD(message); + message += 4; + } + rmd160::MDcompress(buffer, current); + } + // length mod 64 bytes left + + // finish: + rmd160::MDfinish(buffer, message, _input.size(), 0); + + for (unsigned i = 0; i < RMDsize / 8; i += 4) + { + hashcode[i] = buffer[i >> 2]; // implicit cast to byte + hashcode[i + 1] = (buffer[i >> 2] >> 8); //extracts the 8 least + hashcode[i + 2] = (buffer[i >> 2] >> 16); // significant bits. + hashcode[i + 3] = (buffer[i >> 2] >> 24); + } + + return hashcode; +} + +#undef BYTES_TO_DWORD +#undef RMDsize + +} diff --git a/libdevcrypto/Hash.h b/libdevcrypto/Hash.h new file mode 100644 index 000000000..7c5fcd67a --- /dev/null +++ b/libdevcrypto/Hash.h @@ -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 Hash.h + * @author Gav Wood + * @date 2014 + * + * The FixedHash fixed-size "hash" container type. + */ + +#pragma once + +#include +#include +#include +#include "SHA3.h" + +namespace dev +{ + +h256 sha256(bytesConstRef _input); + +h160 ripemd160(bytesConstRef _input); + +} diff --git a/libdevcrypto/SHA3.cpp b/libdevcrypto/SHA3.cpp index b7a47b745..250936db1 100644 --- a/libdevcrypto/SHA3.cpp +++ b/libdevcrypto/SHA3.cpp @@ -20,8 +20,12 @@ */ #include "SHA3.h" - +#include +#include +#include +#include #include +#include "picosha2.h" #include "CryptoPP.h" using namespace std; using namespace dev; @@ -32,98 +36,189 @@ namespace dev h256 EmptySHA3 = sha3(bytesConstRef()); h256 EmptyListSHA3 = sha3(rlpList()); -std::string sha3(std::string const& _input, bool _hex) +namespace keccak { - if (!_hex) - { - string ret(32, '\0'); - sha3(bytesConstRef((byte const*)_input.data(), _input.size()), bytesRef((byte*)ret.data(), 32)); - return ret; - } - - uint8_t buf[32]; - sha3(bytesConstRef((byte const*)_input.data(), _input.size()), bytesRef((byte*)&(buf[0]), 32)); - std::string ret(64, '\0'); - for (unsigned int i = 0; i < 32; i++) - sprintf((char*)(ret.data())+i*2, "%02x", buf[i]); - return ret; -} -void sha3(bytesConstRef _input, bytesRef _output) -{ - CryptoPP::SHA3_256 ctx; - ctx.Update((byte*)_input.data(), _input.size()); - assert(_output.size() >= 32); - ctx.Final(_output.data()); -} +/** libkeccak-tiny + * + * A single-file implementation of SHA-3 and SHAKE. + * + * Implementor: David Leon Gil + * License: CC0, attribution kindly requested. Blame taken too, + * but not liability. + */ -void ripemd160(bytesConstRef _input, bytesRef _output) -{ - CryptoPP::RIPEMD160 ctx; - ctx.Update((byte*)_input.data(), _input.size()); - assert(_output.size() >= 32); - ctx.Final(_output.data()); +#define decshake(bits) \ + int shake##bits(uint8_t*, size_t, const uint8_t*, size_t); + +#define decsha3(bits) \ + int sha3_##bits(uint8_t*, size_t, const uint8_t*, size_t); + +decshake(128) +decshake(256) +decsha3(224) +decsha3(256) +decsha3(384) +decsha3(512) + +/******** The Keccak-f[1600] permutation ********/ + +/*** 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}; +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}; +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}; + +/*** 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;) + +/*** 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; + + 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]; + } } -void sha256(bytesConstRef _input, bytesRef _output) -{ - CryptoPP::SHA256 ctx; - ctx.Update((byte*)_input.data(), _input.size()); - assert(_output.size() >= 32); - ctx.Final(_output.data()); +/******** The FIPS202-defined functions. ********/ + +/*** 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); \ + } + +mkapply_ds(xorin, dst[i] ^= src[i]) // xorin +mkapply_sd(setout, dst[i] = src[i]) // setout + +#define P keccakf +#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; \ + } + +/** 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; } -bytes sha3Bytes(bytesConstRef _input) -{ - bytes ret(32); - sha3(_input, &ret); - return ret; +/*** Helper macros to define SHA3 and SHAKE instances. ***/ +#define defshake(bits) \ + int shake##bits(uint8_t* out, size_t outlen, \ + const uint8_t* in, size_t inlen) { \ + return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x1f); \ + } +#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 SHAKE VOFs ***/ +defshake(128) +defshake(256) + +/*** FIPS202 SHA3 FOFs ***/ +defsha3(224) +defsha3(256) +defsha3(384) +defsha3(512) + } h256 sha3(bytesConstRef _input) { + // FIXME: What with unaligned memory? h256 ret; - sha3(_input, bytesRef(&ret[0], 32)); + keccak::sha3_256(ret.data(), 32, _input.data(), _input.size()); +// keccak::keccak(ret.data(), 32, (uint64_t const*)_input.data(), _input.size()); return ret; } - -void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output) -{ - CryptoPP::SHA3_256 ctx; - assert(_secret.size() > 0); - ctx.Update((byte*)_secret.data(), _secret.size()); - ctx.Update((byte*)_plain.data(), _plain.size()); - assert(_output.size() >= 32); - ctx.Final(_output.data()); -} - -bytes aesDecrypt(bytesConstRef _ivCipher, std::string const& _password, unsigned _rounds, bytesConstRef _salt) -{ - bytes pw = asBytes(_password); - - if (!_salt.size()) - _salt = &pw; - - bytes target(64); - CryptoPP::PKCS5_PBKDF2_HMAC().DeriveKey(target.data(), target.size(), 0, pw.data(), pw.size(), _salt.data(), _salt.size(), _rounds); - - try - { - CryptoPP::AES::Decryption aesDecryption(target.data(), 16); - auto cipher = _ivCipher.cropped(16); - auto iv = _ivCipher.cropped(0, 16); - CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data()); - std::string decrypted; - CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(decrypted)); - stfDecryptor.Put(cipher.data(), cipher.size()); - stfDecryptor.MessageEnd(); - return asBytes(decrypted); - } - catch (exception const& e) - { - cerr << e.what() << endl; - return bytes(); - } -} } diff --git a/libdevcrypto/SHA3.h b/libdevcrypto/SHA3.h index 66b8efe11..c3ef524fe 100644 --- a/libdevcrypto/SHA3.h +++ b/libdevcrypto/SHA3.h @@ -32,46 +32,29 @@ namespace dev // SHA-3 convenience routines. -/// Calculate SHA3-256 hash of the given input and load it into the given output. -void sha3(bytesConstRef _input, bytesRef _output); - -/// Calculate SHA3-256 hash of the given input, possibly interpreting it as nibbles, and return the hash as a string filled with binary data. -std::string sha3(std::string const& _input, bool _isNibbles); - -/// Calculate SHA3-256 hash of the given input, returning as a byte array. -bytes sha3Bytes(bytesConstRef _input); - -/// Calculate SHA3-256 hash of the given input (presented as a binary string), returning as a byte array. -inline bytes sha3Bytes(std::string const& _input) { return sha3Bytes((std::string*)&_input); } - -/// Calculate SHA3-256 hash of the given input, returning as a byte array. -inline bytes sha3Bytes(bytes const& _input) { return sha3Bytes((bytes*)&_input); } - /// Calculate SHA3-256 hash of the given input, returning as a 256-bit hash. h256 sha3(bytesConstRef _input); +/// Calculate SHA3-256 hash of the given input and load it into the given output. +inline void sha3(bytesConstRef _input, bytesRef _output) { sha3(_input).ref().populate(_output); } + /// Calculate SHA3-256 hash of the given input, returning as a 256-bit hash. -inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef((bytes*)&_input)); } +inline h256 sha3(bytes const& _input) { return sha3(bytesConstRef(&_input)); } /// Calculate SHA3-256 hash of the given input (presented as a binary-filled string), returning as a 256-bit hash. inline h256 sha3(std::string const& _input) { return sha3(bytesConstRef(_input)); } - -/// Calculate SHA3-256 MAC -void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output); /// Calculate SHA3-256 hash of the given input (presented as a FixedHash), returns a 256-bit hash. template inline h256 sha3(FixedHash const& _input) { return sha3(_input.ref()); } -extern h256 EmptySHA3; - -extern h256 EmptyListSHA3; - -// Other crypto convenience routines +/// Calculate SHA3-256 hash of the given input, possibly interpreting it as nibbles, and return the hash as a string filled with binary data. +inline std::string sha3(std::string const& _input, bool _isNibbles) { return asString((_isNibbles ? sha3(fromHex(_input)) : sha3(bytesConstRef(&_input))).asBytes()); } -bytes aesDecrypt(bytesConstRef _cipher, std::string const& _password, unsigned _rounds = 2000, bytesConstRef _salt = bytesConstRef()); +/// Calculate SHA3-256 MAC +inline void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output) { sha3(_secret.toBytes() + _plain.toBytes()).ref().populate(_output); } -void sha256(bytesConstRef _input, bytesRef _output); +extern h256 EmptySHA3; -void ripemd160(bytesConstRef _input, bytesRef _output); +extern h256 EmptyListSHA3; } diff --git a/libdevcrypto/picosha2.h b/libdevcrypto/picosha2.h new file mode 100644 index 000000000..44b6bee59 --- /dev/null +++ b/libdevcrypto/picosha2.h @@ -0,0 +1,360 @@ +/* +The MIT License (MIT) + +Copyright (C) 2014 okdshin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +#ifndef PICOSHA2_H +#define PICOSHA2_H +//picosha2:20140213 +#include +#include +#include +#include +#include +#include +#include + +namespace picosha2 +{ + +namespace detail +{ + +inline uint8_t mask_8bit(uint8_t x){ + return x&0xff; +} + +inline uint32_t mask_32bit(uint32_t x){ + return x&0xffffffff; +} + +static const uint32_t add_constant[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +static const uint32_t initial_message_digest[8] = { + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 +}; + +inline uint32_t ch(uint32_t x, uint32_t y, uint32_t z){ + return (x&y)^((~x)&z); +} + +inline uint32_t maj(uint32_t x, uint32_t y, uint32_t z){ + return (x&y)^(x&z)^(y&z); +} + +inline uint32_t rotr(uint32_t x, std::size_t n){ + assert(n < 32); + return mask_32bit((x>>n)|(x<<(32-n))); +} + +inline uint32_t bsig0(uint32_t x){ + return rotr(x, 2)^rotr(x, 13)^rotr(x, 22); +} + +inline uint32_t bsig1(uint32_t x){ + return rotr(x, 6)^rotr(x, 11)^rotr(x, 25); +} + +inline uint32_t shr(uint32_t x, std::size_t n){ + assert(n < 32); + return x >> n; +} + +inline uint32_t ssig0(uint32_t x){ + return rotr(x, 7)^rotr(x, 18)^shr(x, 3); +} + +inline uint32_t ssig1(uint32_t x){ + return rotr(x, 17)^rotr(x, 19)^shr(x, 10); +} + +template +void hash256_block(RaIter1 message_digest, RaIter2 first, RaIter2 last){ + (void)last; // FIXME: check this is valid + uint32_t w[64]; + std::fill(w, w+64, 0); + for(std::size_t i = 0; i < 16; ++i){ + w[i] = (static_cast(mask_8bit(*(first+i*4)))<<24) + |(static_cast(mask_8bit(*(first+i*4+1)))<<16) + |(static_cast(mask_8bit(*(first+i*4+2)))<<8) + |(static_cast(mask_8bit(*(first+i*4+3)))); + } + for(std::size_t i = 16; i < 64; ++i){ + w[i] = mask_32bit(ssig1(w[i-2])+w[i-7]+ssig0(w[i-15])+w[i-16]); + } + + uint32_t a = *message_digest; + uint32_t b = *(message_digest+1); + uint32_t c = *(message_digest+2); + uint32_t d = *(message_digest+3); + uint32_t e = *(message_digest+4); + uint32_t f = *(message_digest+5); + uint32_t g = *(message_digest+6); + uint32_t h = *(message_digest+7); + + for(std::size_t i = 0; i < 64; ++i){ + uint32_t temp1 = h+bsig1(e)+ch(e,f,g)+add_constant[i]+w[i]; + uint32_t temp2 = bsig0(a)+maj(a,b,c); + h = g; + g = f; + f = e; + e = mask_32bit(d+temp1); + d = c; + c = b; + b = a; + a = mask_32bit(temp1+temp2); + } + *message_digest += a; + *(message_digest+1) += b; + *(message_digest+2) += c; + *(message_digest+3) += d; + *(message_digest+4) += e; + *(message_digest+5) += f; + *(message_digest+6) += g; + *(message_digest+7) += h; + for(std::size_t i = 0; i < 8; ++i){ + *(message_digest+i) = mask_32bit(*(message_digest+i)); + } +} + +}//namespace detail + +template +void output_hex(InIter first, InIter last, std::ostream& os){ + os.setf(std::ios::hex, std::ios::basefield); + while(first != last){ + os.width(2); + os.fill('0'); + os << static_cast(*first); + ++first; + } + os.setf(std::ios::dec, std::ios::basefield); +} + +template +void bytes_to_hex_string(InIter first, InIter last, std::string& hex_str){ + std::ostringstream oss; + output_hex(first, last, oss); + hex_str.assign(oss.str()); +} + +template +void bytes_to_hex_string(const InContainer& bytes, std::string& hex_str){ + bytes_to_hex_string(bytes.begin(), bytes.end(), hex_str); +} + +template +std::string bytes_to_hex_string(InIter first, InIter last){ + std::string hex_str; + bytes_to_hex_string(first, last, hex_str); + return hex_str; +} + +template +std::string bytes_to_hex_string(const InContainer& bytes){ + std::string hex_str; + bytes_to_hex_string(bytes, hex_str); + return hex_str; +} + +class hash256_one_by_one { +public: + hash256_one_by_one(){ + init(); + } + + void init(){ + buffer_.clear(); + std::fill(data_length_digits_, data_length_digits_+4, 0); + std::copy(detail::initial_message_digest, detail::initial_message_digest+8, h_); + } + + template + void process(RaIter first, RaIter last){ + add_to_data_length(std::distance(first, last)); + std::copy(first, last, std::back_inserter(buffer_)); + std::size_t i = 0; + for(;i+64 <= buffer_.size(); i+=64){ + detail::hash256_block(h_, buffer_.begin()+i, buffer_.begin()+i+64); + } + buffer_.erase(buffer_.begin(), buffer_.begin()+i); + } + + void finish(){ + uint8_t temp[64]; + std::fill(temp, temp+64, 0); + std::size_t remains = buffer_.size(); + std::copy(buffer_.begin(), buffer_.end(), temp); + temp[remains] = 0x80; + + if(remains > 55){ + std::fill(temp+remains+1, temp+64, 0); + detail::hash256_block(h_, temp, temp+64); + std::fill(temp, temp+64-4, 0); + } + else { + std::fill(temp+remains+1, temp+64-4, 0); + } + + write_data_bit_length(&(temp[56])); + detail::hash256_block(h_, temp, temp+64); + } + + template + void get_hash_bytes(OutIter first, OutIter last)const{ + for(const uint32_t* iter = h_; iter != h_+8; ++iter){ + for(std::size_t i = 0; i < 4 && first != last; ++i){ + *(first++) = detail::mask_8bit(static_cast((*iter >> (24-8*i)))); + } + } + } + +private: + void add_to_data_length(uint32_t n) { + uint32_t carry = 0; + data_length_digits_[0] += n; + for(std::size_t i = 0; i < 4; ++i) { + data_length_digits_[i] += carry; + if(data_length_digits_[i] >= 65536u) { + data_length_digits_[i] -= 65536u; + carry = 1; + } + else { + break; + } + } + } + void write_data_bit_length(uint8_t* begin) { + uint32_t data_bit_length_digits[4]; + std::copy( + data_length_digits_, data_length_digits_+4, + data_bit_length_digits + ); + + // convert byte length to bit length (multiply 8 or shift 3 times left) + uint32_t carry = 0; + for(std::size_t i = 0; i < 4; ++i) { + uint32_t before_val = data_bit_length_digits[i]; + data_bit_length_digits[i] <<= 3; + data_bit_length_digits[i] |= carry; + data_bit_length_digits[i] &= 65535u; + carry = (before_val >> (16-3)) & 65535u; + } + + // write data_bit_length + for(int i = 3; i >= 0; --i) { + (*begin++) = static_cast(data_bit_length_digits[i] >> 8); + (*begin++) = static_cast(data_bit_length_digits[i]); + } + } + std::vector buffer_; + uint32_t data_length_digits_[4]; //as 64bit integer (16bit x 4 integer) + uint32_t h_[8]; +}; + +inline void get_hash_hex_string(const hash256_one_by_one& hasher, std::string& hex_str){ + uint8_t hash[32]; + hasher.get_hash_bytes(hash, hash+32); + return bytes_to_hex_string(hash, hash+32, hex_str); +} + +inline std::string get_hash_hex_string(const hash256_one_by_one& hasher){ + std::string hex_str; + get_hash_hex_string(hasher, hex_str); + return hex_str; +} + +template +void hash256(RaIter first, RaIter last, OutIter first2, OutIter last2){ + hash256_one_by_one hasher; + //hasher.init(); + hasher.process(first, last); + hasher.finish(); + hasher.get_hash_bytes(first2, last2); +} + +template +void hash256(RaIter first, RaIter last, OutContainer& dst){ + hash256(first, last, dst.begin(), dst.end()); +} + +template +void hash256(const RaContainer& src, OutIter first, OutIter last){ + hash256(src.begin(), src.end(), first, last); +} + +template +void hash256(const RaContainer& src, OutContainer& dst){ + hash256(src.begin(), src.end(), dst.begin(), dst.end()); +} + + +template +void hash256_hex_string(RaIter first, RaIter last, std::string& hex_str){ + uint8_t hashed[32]; + hash256(first, last, hashed, hashed+32); + std::ostringstream oss; + output_hex(hashed, hashed+32, oss); + hex_str.assign(oss.str()); +} + +template +std::string hash256_hex_string(RaIter first, RaIter last){ + std::string hex_str; + hash256_hex_string(first, last, hex_str); + return hex_str; +} + +inline void hash256_hex_string(const std::string& src, std::string& hex_str){ + hash256_hex_string(src.begin(), src.end(), hex_str); +} + +template +void hash256_hex_string(const RaContainer& src, std::string& hex_str){ + hash256_hex_string(src.begin(), src.end(), hex_str); +} + +template +std::string hash256_hex_string(const RaContainer& src){ + return hash256_hex_string(src.begin(), src.end()); +} + +}//namespace picosha2 + +#endif //PICOSHA2_H diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index cdcb4a46a..9373697e1 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -21,7 +21,9 @@ #include "Precompiled.h" +#include #include +#include #include #include #include @@ -61,19 +63,12 @@ static bytes ecrecoverCode(bytesConstRef _in) static bytes sha256Code(bytesConstRef _in) { - bytes ret(32); - sha256(_in, &ret); - return ret; + return sha256(_in).asBytes(); } static bytes ripemd160Code(bytesConstRef _in) { - bytes ret(32); - ripemd160(_in, &ret); - // leaves the 20-byte hash left-aligned. we want it right-aligned: - memmove(ret.data() + 12, ret.data(), 20); - memset(ret.data(), 0, 12); - return ret; + return h256(ripemd160(_in), h256::AlignRight).asBytes(); } static bytes identityCode(bytesConstRef _in) diff --git a/test/libdevcrypto/crypto.cpp b/test/libdevcrypto/crypto.cpp index 88ff98965..3381c45da 100644 --- a/test/libdevcrypto/crypto.cpp +++ b/test/libdevcrypto/crypto.cpp @@ -45,13 +45,19 @@ static CryptoPP::OID s_curveOID(CryptoPP::ASN1::secp256k1()); static CryptoPP::DL_GroupParameters_EC s_params(s_curveOID); static CryptoPP::DL_GroupParameters_EC::EllipticCurve s_curve(s_params.GetCurve()); -BOOST_AUTO_TEST_CASE(emptySHA3Types) +BOOST_AUTO_TEST_CASE(sha3general) { - h256 emptyListSHA3(fromHex("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")); - BOOST_REQUIRE_EQUAL(emptyListSHA3, EmptyListSHA3); + BOOST_REQUIRE_EQUAL(sha3(""), h256("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); + BOOST_REQUIRE_EQUAL(sha3("hello"), h256("1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8")); +} +BOOST_AUTO_TEST_CASE(emptySHA3Types) +{ h256 emptySHA3(fromHex("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); BOOST_REQUIRE_EQUAL(emptySHA3, EmptySHA3); + + h256 emptyListSHA3(fromHex("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")); + BOOST_REQUIRE_EQUAL(emptyListSHA3, EmptyListSHA3); } BOOST_AUTO_TEST_CASE(cryptopp_patch) @@ -805,7 +811,7 @@ int cryptoTest() std::string hmsg = sha3(t.rlp(false), false); cout << "SHA256(RLP(TX w/o SIG)): 0x" << toHex(hmsg) << endl; - bytes privkey = sha3Bytes("123"); + bytes privkey = sha3("123").asBytes(); { bytes pubkey(65); diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 6713382fa..aa51a674d 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include using namespace std; @@ -1501,9 +1501,7 @@ BOOST_AUTO_TEST_CASE(sha256) compileAndRun(sourceCode); auto f = [&](u256 const& _input) -> u256 { - h256 ret; - dev::sha256(dev::ref(toBigEndian(_input)), bytesRef(&ret[0], 32)); - return ret; + return dev::sha256(dev::ref(toBigEndian(_input))); }; testSolidityAgainstCpp("a(bytes32)", f, u256(4)); testSolidityAgainstCpp("a(bytes32)", f, u256(5)); @@ -1520,9 +1518,7 @@ BOOST_AUTO_TEST_CASE(ripemd) compileAndRun(sourceCode); auto f = [&](u256 const& _input) -> u256 { - h256 ret; - dev::ripemd160(dev::ref(toBigEndian(_input)), bytesRef(&ret[0], 32)); - return u256(ret); + return h256(dev::ripemd160(h256(_input).ref()), h256::AlignLeft); // This should be aligned right. i guess it's fixed elsewhere? }; testSolidityAgainstCpp("a(bytes32)", f, u256(4)); testSolidityAgainstCpp("a(bytes32)", f, u256(5)); From 05ea9941c9b468222026ad9923964456ce195496 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 19 May 2015 19:51:38 +0200 Subject: [PATCH 148/157] Move non-cryptopp dependent stuff into devcore. --- abi/main.cpp | 2 +- alethzero/DappLoader.cpp | 2 +- alethzero/MainWin.cpp | 2 +- alethzero/NatspecHandler.cpp | 2 +- eth/main.cpp | 2 +- ethminer/MinerAux.h | 4 ++-- ethminer/main.cpp | 2 +- evmjit/libevmjit-cpp/Env.cpp | 2 +- evmjit/libevmjit-cpp/JitVM.cpp | 2 +- exp/main.cpp | 4 ++-- {libdevcrypto => libdevcore}/FileSystem.cpp | 4 ++-- {libdevcrypto => libdevcore}/FileSystem.h | 0 {libdevcrypto => libdevcore}/Hash.cpp | 0 {libdevcrypto => libdevcore}/Hash.h | 0 {libdevcrypto => libdevcore}/MemoryDB.cpp | 0 {libdevcrypto => libdevcore}/MemoryDB.h | 0 {libdevcrypto => libdevcore}/OverlayDB.cpp | 0 {libdevcrypto => libdevcore}/OverlayDB.h | 0 {libdevcrypto => libdevcore}/SHA3.cpp | 1 - {libdevcrypto => libdevcore}/SHA3.h | 0 {libdevcrypto => libdevcore}/TrieCommon.cpp | 0 {libdevcrypto => libdevcore}/TrieCommon.h | 0 {libdevcrypto => libdevcore}/TrieDB.cpp | 0 {libdevcrypto => libdevcore}/TrieDB.h | 2 +- {libdevcrypto => libdevcore}/TrieHash.cpp | 6 +++--- {libdevcrypto => libdevcore}/TrieHash.h | 0 {libdevcrypto => libdevcore}/picosha2.h | 0 libdevcrypto/Common.cpp | 4 ++-- libdevcrypto/CryptoPP.h | 2 +- libdevcrypto/ECDHE.cpp | 4 ++-- libdevcrypto/SecretStore.cpp | 4 ++-- libdevcrypto/SecretStore.h | 2 +- libethcore/ABI.h | 2 +- libethcore/BlockInfo.cpp | 4 ++-- libethcore/Common.cpp | 2 +- libethcore/Ethash.cpp | 2 +- libethcore/EthashAux.cpp | 4 ++-- libethcore/ICAP.cpp | 2 +- libethereum/Account.h | 4 ++-- libethereum/BlockChain.cpp | 2 +- libethereum/CachedAddressState.cpp | 2 +- libethereum/CanonBlockChain.cpp | 2 +- libethereum/Defaults.cpp | 2 +- libethereum/KeyManager.h | 2 +- libethereum/LogFilter.cpp | 2 +- libethereum/Precompiled.cpp | 4 ++-- libethereum/State.cpp | 2 +- libethereum/State.h | 2 +- libethereum/Transaction.h | 2 +- libethereum/Utility.cpp | 2 +- libevm/ExtVMFace.h | 2 +- libevm/SmartVM.cpp | 2 +- libevm/VM.h | 2 +- libevmasm/CommonSubexpressionEliminator.cpp | 2 +- libevmasm/KnownState.cpp | 2 +- libp2p/Host.cpp | 2 +- libp2p/UDP.h | 2 +- libsolidity/AST.cpp | 2 +- libsolidity/CompilerStack.cpp | 2 +- libsolidity/ExpressionCompiler.cpp | 2 +- libsolidity/Types.cpp | 2 +- libtestutils/Common.cpp | 2 +- libweb3jsonrpc/WebThreeStubServer.cpp | 2 +- libwhisper/Common.cpp | 2 +- libwhisper/Interface.h | 2 +- libwhisper/Message.h | 2 +- libwhisper/WhisperHost.h | 2 +- libwhisper/WhisperPeer.h | 2 +- mix/FileIo.cpp | 2 +- mix/QFunctionDefinition.cpp | 2 +- neth/main.cpp | 2 +- rlp/main.cpp | 2 +- test/deprecated/main.cpp | 2 +- test/libdevcrypto/MemTrie.cpp | 4 ++-- test/libdevcrypto/crypto.cpp | 2 +- test/libdevcrypto/hexPrefix.cpp | 2 +- test/libdevcrypto/trie.cpp | 4 ++-- test/libethereum/blockchain.cpp | 2 +- test/libp2p/rlpx.cpp | 2 +- test/libsolidity/SolidityEndToEndTest.cpp | 2 +- test/libsolidity/SolidityNameAndTypeResolution.cpp | 2 +- third/MainWin.cpp | 2 +- 82 files changed, 82 insertions(+), 83 deletions(-) rename {libdevcrypto => libdevcore}/FileSystem.cpp (97%) rename {libdevcrypto => libdevcore}/FileSystem.h (100%) rename {libdevcrypto => libdevcore}/Hash.cpp (100%) rename {libdevcrypto => libdevcore}/Hash.h (100%) rename {libdevcrypto => libdevcore}/MemoryDB.cpp (100%) rename {libdevcrypto => libdevcore}/MemoryDB.h (100%) rename {libdevcrypto => libdevcore}/OverlayDB.cpp (100%) rename {libdevcrypto => libdevcore}/OverlayDB.h (100%) rename {libdevcrypto => libdevcore}/SHA3.cpp (99%) rename {libdevcrypto => libdevcore}/SHA3.h (100%) rename {libdevcrypto => libdevcore}/TrieCommon.cpp (100%) rename {libdevcrypto => libdevcore}/TrieCommon.h (100%) rename {libdevcrypto => libdevcore}/TrieDB.cpp (100%) rename {libdevcrypto => libdevcore}/TrieDB.h (99%) rename {libdevcrypto => libdevcore}/TrieHash.cpp (97%) rename {libdevcrypto => libdevcore}/TrieHash.h (100%) rename {libdevcrypto => libdevcore}/picosha2.h (100%) diff --git a/abi/main.cpp b/abi/main.cpp index 27c5eea1b..df7fa8811 100644 --- a/abi/main.cpp +++ b/abi/main.cpp @@ -26,7 +26,7 @@ #include "../test/JsonSpiritHeaders.h" #include #include -#include +#include #include using namespace std; using namespace dev; diff --git a/alethzero/DappLoader.cpp b/alethzero/DappLoader.cpp index a91beb2f7..b2249ae5b 100644 --- a/alethzero/DappLoader.cpp +++ b/alethzero/DappLoader.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 9486f9f01..b59e9ce1f 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -44,7 +44,7 @@ #include #include #endif -#include +#include #include #include #include diff --git a/alethzero/NatspecHandler.cpp b/alethzero/NatspecHandler.cpp index a7cad6853..d00abc44f 100644 --- a/alethzero/NatspecHandler.cpp +++ b/alethzero/NatspecHandler.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include using namespace dev; diff --git a/eth/main.cpp b/eth/main.cpp index 1cf918346..33d049843 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include #include diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 040bd945c..8e480a3ff 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -31,11 +31,11 @@ #include #include -#include +#include #include #include #include -#include +#include #include #include #include diff --git a/ethminer/main.cpp b/ethminer/main.cpp index 5b82db471..4deba38d1 100644 --- a/ethminer/main.cpp +++ b/ethminer/main.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include "MinerAux.h" using namespace std; using namespace dev; diff --git a/evmjit/libevmjit-cpp/Env.cpp b/evmjit/libevmjit-cpp/Env.cpp index a5a60f48c..d1f239f9f 100644 --- a/evmjit/libevmjit-cpp/Env.cpp +++ b/evmjit/libevmjit-cpp/Env.cpp @@ -1,6 +1,6 @@ #pragma GCC diagnostic ignored "-Wconversion" -#include +#include #include #include #include diff --git a/evmjit/libevmjit-cpp/JitVM.cpp b/evmjit/libevmjit-cpp/JitVM.cpp index 7acbec5c1..6efd4c31a 100644 --- a/evmjit/libevmjit-cpp/JitVM.cpp +++ b/evmjit/libevmjit-cpp/JitVM.cpp @@ -4,7 +4,7 @@ #include "JitVM.h" #include -#include +#include #include #include #include diff --git a/exp/main.cpp b/exp/main.cpp index 138ae76a4..d31306496 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -41,12 +41,12 @@ #include #include #include -#include +#include #include #include #include #include -#include +#include #include #include #include diff --git a/libdevcrypto/FileSystem.cpp b/libdevcore/FileSystem.cpp similarity index 97% rename from libdevcrypto/FileSystem.cpp rename to libdevcore/FileSystem.cpp index adf3a2946..dfda891f5 100644 --- a/libdevcrypto/FileSystem.cpp +++ b/libdevcore/FileSystem.cpp @@ -22,8 +22,8 @@ */ #include "FileSystem.h" -#include -#include +#include "Common.h" +#include "Log.h" #if defined(_WIN32) #include diff --git a/libdevcrypto/FileSystem.h b/libdevcore/FileSystem.h similarity index 100% rename from libdevcrypto/FileSystem.h rename to libdevcore/FileSystem.h diff --git a/libdevcrypto/Hash.cpp b/libdevcore/Hash.cpp similarity index 100% rename from libdevcrypto/Hash.cpp rename to libdevcore/Hash.cpp diff --git a/libdevcrypto/Hash.h b/libdevcore/Hash.h similarity index 100% rename from libdevcrypto/Hash.h rename to libdevcore/Hash.h diff --git a/libdevcrypto/MemoryDB.cpp b/libdevcore/MemoryDB.cpp similarity index 100% rename from libdevcrypto/MemoryDB.cpp rename to libdevcore/MemoryDB.cpp diff --git a/libdevcrypto/MemoryDB.h b/libdevcore/MemoryDB.h similarity index 100% rename from libdevcrypto/MemoryDB.h rename to libdevcore/MemoryDB.h diff --git a/libdevcrypto/OverlayDB.cpp b/libdevcore/OverlayDB.cpp similarity index 100% rename from libdevcrypto/OverlayDB.cpp rename to libdevcore/OverlayDB.cpp diff --git a/libdevcrypto/OverlayDB.h b/libdevcore/OverlayDB.h similarity index 100% rename from libdevcrypto/OverlayDB.h rename to libdevcore/OverlayDB.h diff --git a/libdevcrypto/SHA3.cpp b/libdevcore/SHA3.cpp similarity index 99% rename from libdevcrypto/SHA3.cpp rename to libdevcore/SHA3.cpp index 250936db1..880f23d6e 100644 --- a/libdevcrypto/SHA3.cpp +++ b/libdevcore/SHA3.cpp @@ -26,7 +26,6 @@ #include #include #include "picosha2.h" -#include "CryptoPP.h" using namespace std; using namespace dev; diff --git a/libdevcrypto/SHA3.h b/libdevcore/SHA3.h similarity index 100% rename from libdevcrypto/SHA3.h rename to libdevcore/SHA3.h diff --git a/libdevcrypto/TrieCommon.cpp b/libdevcore/TrieCommon.cpp similarity index 100% rename from libdevcrypto/TrieCommon.cpp rename to libdevcore/TrieCommon.cpp diff --git a/libdevcrypto/TrieCommon.h b/libdevcore/TrieCommon.h similarity index 100% rename from libdevcrypto/TrieCommon.h rename to libdevcore/TrieCommon.h diff --git a/libdevcrypto/TrieDB.cpp b/libdevcore/TrieDB.cpp similarity index 100% rename from libdevcrypto/TrieDB.cpp rename to libdevcore/TrieDB.cpp diff --git a/libdevcrypto/TrieDB.h b/libdevcore/TrieDB.h similarity index 99% rename from libdevcrypto/TrieDB.h rename to libdevcore/TrieDB.h index cf85148d2..13a520311 100644 --- a/libdevcrypto/TrieDB.h +++ b/libdevcore/TrieDB.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include "MemoryDB.h" #include "OverlayDB.h" #include "TrieCommon.h" diff --git a/libdevcrypto/TrieHash.cpp b/libdevcore/TrieHash.cpp similarity index 97% rename from libdevcrypto/TrieHash.cpp rename to libdevcore/TrieHash.cpp index 0b02ce77f..ec0a92f90 100644 --- a/libdevcrypto/TrieHash.cpp +++ b/libdevcore/TrieHash.cpp @@ -20,9 +20,9 @@ */ #include "TrieHash.h" -#include -#include // @TODO replace ASAP! -#include +#include +#include // @TODO replace ASAP! +#include #include using namespace std; using namespace dev; diff --git a/libdevcrypto/TrieHash.h b/libdevcore/TrieHash.h similarity index 100% rename from libdevcrypto/TrieHash.h rename to libdevcore/TrieHash.h diff --git a/libdevcrypto/picosha2.h b/libdevcore/picosha2.h similarity index 100% rename from libdevcrypto/picosha2.h rename to libdevcore/picosha2.h diff --git a/libdevcrypto/Common.cpp b/libdevcrypto/Common.cpp index 52be6ce3b..87e258573 100644 --- a/libdevcrypto/Common.cpp +++ b/libdevcrypto/Common.cpp @@ -26,9 +26,9 @@ #include #include #include -#include "SHA3.h" +#include +#include #include "AES.h" -#include "FileSystem.h" #include "CryptoPP.h" using namespace std; using namespace dev; diff --git a/libdevcrypto/CryptoPP.h b/libdevcrypto/CryptoPP.h index 4991e3713..ca8a2e6b5 100644 --- a/libdevcrypto/CryptoPP.h +++ b/libdevcrypto/CryptoPP.h @@ -49,7 +49,7 @@ #include #pragma warning(pop) #pragma GCC diagnostic pop -#include "SHA3.h" +#include #include "Common.h" namespace dev diff --git a/libdevcrypto/ECDHE.cpp b/libdevcrypto/ECDHE.cpp index a00a92872..a5aaf3984 100644 --- a/libdevcrypto/ECDHE.cpp +++ b/libdevcrypto/ECDHE.cpp @@ -19,9 +19,9 @@ * @date 2014 */ -#include "SHA3.h" -#include "CryptoPP.h" #include "ECDHE.h" +#include +#include "CryptoPP.h" using namespace std; using namespace dev; diff --git a/libdevcrypto/SecretStore.cpp b/libdevcrypto/SecretStore.cpp index 9be0b89e8..0416aa9f4 100644 --- a/libdevcrypto/SecretStore.cpp +++ b/libdevcrypto/SecretStore.cpp @@ -25,9 +25,9 @@ #include #include #include +#include +#include #include -#include "SHA3.h" -#include "FileSystem.h" using namespace std; using namespace dev; namespace js = json_spirit; diff --git a/libdevcrypto/SecretStore.h b/libdevcrypto/SecretStore.h index 1fb6adf4a..18c290c1f 100644 --- a/libdevcrypto/SecretStore.h +++ b/libdevcrypto/SecretStore.h @@ -24,8 +24,8 @@ #include #include #include +#include #include "Common.h" -#include "FileSystem.h" namespace dev { diff --git a/libethcore/ABI.h b/libethcore/ABI.h index 7fca09c9a..09aca6754 100644 --- a/libethcore/ABI.h +++ b/libethcore/ABI.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include namespace dev { diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index 00a5108c4..22e171e31 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -21,8 +21,8 @@ #include #include -#include -#include +#include +#include #include #include #include "EthashAux.h" diff --git a/libethcore/Common.cpp b/libethcore/Common.cpp index c74aeba5e..56db647f3 100644 --- a/libethcore/Common.cpp +++ b/libethcore/Common.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "Exceptions.h" #include "ProofOfWork.h" using namespace std; diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 6276dd0a1..1f16166f0 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #if ETH_ETHASHCL || !ETH_TRUE diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index eccb986a7..38425aca2 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -31,8 +31,8 @@ #include #include #include -#include -#include +#include +#include #include #include "BlockInfo.h" #include "Exceptions.h" diff --git a/libethcore/ICAP.cpp b/libethcore/ICAP.cpp index 6fce19a62..158c297f8 100644 --- a/libethcore/ICAP.cpp +++ b/libethcore/ICAP.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "Exceptions.h" #include "ABI.h" using namespace std; diff --git a/libethereum/Account.h b/libethereum/Account.h index 660dc0a4c..87fc82b6c 100644 --- a/libethereum/Account.h +++ b/libethereum/Account.h @@ -23,8 +23,8 @@ #include #include -#include -#include +#include +#include namespace dev { diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 73747b25b..c46127303 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libethereum/CachedAddressState.cpp b/libethereum/CachedAddressState.cpp index a25017793..7c2f0a80c 100644 --- a/libethereum/CachedAddressState.cpp +++ b/libethereum/CachedAddressState.cpp @@ -22,7 +22,7 @@ #include "CachedAddressState.h" #include -#include +#include #include "Account.h" using namespace std; using namespace dev; diff --git a/libethereum/CanonBlockChain.cpp b/libethereum/CanonBlockChain.cpp index f1de7292b..5dd7dc2ce 100644 --- a/libethereum/CanonBlockChain.cpp +++ b/libethereum/CanonBlockChain.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libethereum/Defaults.cpp b/libethereum/Defaults.cpp index febe53d84..b839bbb5c 100644 --- a/libethereum/Defaults.cpp +++ b/libethereum/Defaults.cpp @@ -21,7 +21,7 @@ #include "Defaults.h" -#include +#include using namespace std; using namespace dev; using namespace dev::eth; diff --git a/libethereum/KeyManager.h b/libethereum/KeyManager.h index 38e8d8853..bb537e1f1 100644 --- a/libethereum/KeyManager.h +++ b/libethereum/KeyManager.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include namespace dev { diff --git a/libethereum/LogFilter.cpp b/libethereum/LogFilter.cpp index ab9848d59..21ba9d3ef 100644 --- a/libethereum/LogFilter.cpp +++ b/libethereum/LogFilter.cpp @@ -21,7 +21,7 @@ #include "LogFilter.h" -#include +#include #include "State.h" using namespace std; using namespace dev; diff --git a/libethereum/Precompiled.cpp b/libethereum/Precompiled.cpp index 9373697e1..0e80949fe 100644 --- a/libethereum/Precompiled.cpp +++ b/libethereum/Precompiled.cpp @@ -22,8 +22,8 @@ #include "Precompiled.h" #include -#include -#include +#include +#include #include #include #include diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 3bf7aaff7..d302e7381 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libethereum/State.h b/libethereum/State.h index d9fc9d2b5..971c2220a 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h index 78852b7b8..09d6cd54c 100644 --- a/libethereum/Transaction.h +++ b/libethereum/Transaction.h @@ -22,7 +22,7 @@ #pragma once #include -#include +#include #include #include namespace dev diff --git a/libethereum/Utility.cpp b/libethereum/Utility.cpp index 7b0a961b2..adfea4a51 100644 --- a/libethereum/Utility.cpp +++ b/libethereum/Utility.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include using namespace std; using namespace dev; using namespace dev::eth; diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 48fbd0b01..8ebfd8fa5 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libevm/SmartVM.cpp b/libevm/SmartVM.cpp index 4f759a745..89397987e 100644 --- a/libevm/SmartVM.cpp +++ b/libevm/SmartVM.cpp @@ -21,7 +21,7 @@ #include "SmartVM.h" #include #include -#include +#include #include #include #include "VMFactory.h" diff --git a/libevm/VM.h b/libevm/VM.h index 668544f9d..181fcdc2e 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include "VMFace.h" diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index 9f6f9dd63..b2fa73116 100644 --- a/libevmasm/CommonSubexpressionEliminator.cpp +++ b/libevmasm/CommonSubexpressionEliminator.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index 0aac9cedb..895778ed1 100644 --- a/libevmasm/KnownState.cpp +++ b/libevmasm/KnownState.cpp @@ -23,7 +23,7 @@ #include "KnownState.h" #include -#include +#include #include using namespace std; diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index e2599c1d5..998579a90 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include "Session.h" #include "Common.h" #include "Capability.h" diff --git a/libp2p/UDP.h b/libp2p/UDP.h index b09d556e7..a455b5057 100644 --- a/libp2p/UDP.h +++ b/libp2p/UDP.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include #include "Common.h" diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 9842901e7..14884254e 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -28,7 +28,7 @@ #include #include -#include +#include using namespace std; diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp index b3fedc45d..bffa4158f 100644 --- a/libsolidity/CompilerStack.cpp +++ b/libsolidity/CompilerStack.cpp @@ -31,7 +31,7 @@ #include #include -#include +#include using namespace std; diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 838ee264e..2e513b7fc 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index d1f51decf..7577b83a1 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include diff --git a/libtestutils/Common.cpp b/libtestutils/Common.cpp index 5767be32c..cff21d464 100644 --- a/libtestutils/Common.cpp +++ b/libtestutils/Common.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "Common.h" using namespace std; diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 5235b0c4f..44f7f521c 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -26,7 +26,7 @@ #include #include -#include +#include #include "WebThreeStubServer.h" using namespace std; diff --git a/libwhisper/Common.cpp b/libwhisper/Common.cpp index c29ac6bf6..dd9172c70 100644 --- a/libwhisper/Common.cpp +++ b/libwhisper/Common.cpp @@ -21,7 +21,7 @@ #include "Common.h" -#include +#include #include "Message.h" using namespace std; using namespace dev; diff --git a/libwhisper/Interface.h b/libwhisper/Interface.h index db595e21e..8b84193aa 100644 --- a/libwhisper/Interface.h +++ b/libwhisper/Interface.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include "Common.h" #include "Message.h" diff --git a/libwhisper/Message.h b/libwhisper/Message.h index bd73df268..893602190 100644 --- a/libwhisper/Message.h +++ b/libwhisper/Message.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include "Common.h" namespace dev diff --git a/libwhisper/WhisperHost.h b/libwhisper/WhisperHost.h index ebbbcf8ed..cd427da35 100644 --- a/libwhisper/WhisperHost.h +++ b/libwhisper/WhisperHost.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include "Common.h" #include "WhisperPeer.h" #include "Interface.h" diff --git a/libwhisper/WhisperPeer.h b/libwhisper/WhisperPeer.h index 8542e987d..ab9c8222a 100644 --- a/libwhisper/WhisperPeer.h +++ b/libwhisper/WhisperPeer.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include "Common.h" #include "Message.h" diff --git a/mix/FileIo.cpp b/mix/FileIo.cpp index 22538194c..cf8300677 100644 --- a/mix/FileIo.cpp +++ b/mix/FileIo.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include "FileIo.h" using namespace dev; diff --git a/mix/QFunctionDefinition.cpp b/mix/QFunctionDefinition.cpp index 13dbd4821..e6764d712 100644 --- a/mix/QFunctionDefinition.cpp +++ b/mix/QFunctionDefinition.cpp @@ -20,7 +20,7 @@ */ #include -#include +#include #include #include "QVariableDeclaration.h" #include "QFunctionDefinition.h" diff --git a/neth/main.cpp b/neth/main.cpp index 7ce64cba5..a6e661d2e 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include #include diff --git a/rlp/main.cpp b/rlp/main.cpp index 5f2f7f358..3924f9c44 100644 --- a/rlp/main.cpp +++ b/rlp/main.cpp @@ -25,7 +25,7 @@ #include "../test/JsonSpiritHeaders.h" #include #include -#include +#include using namespace std; using namespace dev; namespace js = json_spirit; diff --git a/test/deprecated/main.cpp b/test/deprecated/main.cpp index 6ec8885b3..6cb098228 100644 --- a/test/deprecated/main.cpp +++ b/test/deprecated/main.cpp @@ -20,7 +20,7 @@ * Main test functions. */ -#include +#include #include "TrieHash.h" #include "MemTrie.h" diff --git a/test/libdevcrypto/MemTrie.cpp b/test/libdevcrypto/MemTrie.cpp index ab5a13b60..4507d1d80 100644 --- a/test/libdevcrypto/MemTrie.cpp +++ b/test/libdevcrypto/MemTrie.cpp @@ -21,8 +21,8 @@ #include "MemTrie.h" -#include -#include +#include +#include #include using namespace std; using namespace dev; diff --git a/test/libdevcrypto/crypto.cpp b/test/libdevcrypto/crypto.cpp index 3381c45da..497887145 100644 --- a/test/libdevcrypto/crypto.cpp +++ b/test/libdevcrypto/crypto.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/libdevcrypto/hexPrefix.cpp b/test/libdevcrypto/hexPrefix.cpp index c72f24535..223f1ac7b 100644 --- a/test/libdevcrypto/hexPrefix.cpp +++ b/test/libdevcrypto/hexPrefix.cpp @@ -27,7 +27,7 @@ #include "../JsonSpiritHeaders.h" #include #include -#include +#include #include "../TestHelper.h" using namespace std; diff --git a/test/libdevcrypto/trie.cpp b/test/libdevcrypto/trie.cpp index ecfc515aa..3d6d493dd 100644 --- a/test/libdevcrypto/trie.cpp +++ b/test/libdevcrypto/trie.cpp @@ -27,8 +27,8 @@ #include "../JsonSpiritHeaders.h" #include -#include -#include +#include +#include #include "MemTrie.h" #include "../TestHelper.h" diff --git a/test/libethereum/blockchain.cpp b/test/libethereum/blockchain.cpp index 191b94cc3..4e98b4036 100644 --- a/test/libethereum/blockchain.cpp +++ b/test/libethereum/blockchain.cpp @@ -21,7 +21,7 @@ */ #include -#include +#include #include #include #include diff --git a/test/libp2p/rlpx.cpp b/test/libp2p/rlpx.cpp index 6a86652fb..620ddd952 100644 --- a/test/libp2p/rlpx.cpp +++ b/test/libp2p/rlpx.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index aa51a674d..90ce20d26 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include using namespace std; diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 4ec7b8bda..c52bbf9de 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include #include diff --git a/third/MainWin.cpp b/third/MainWin.cpp index 12625ffbc..3cfc016e3 100644 --- a/third/MainWin.cpp +++ b/third/MainWin.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include From 715a63620bd9ac7a51164f45dec2a694962b7ab1 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 19 May 2015 20:04:48 +0200 Subject: [PATCH 149/157] Move OverlayDB (leveldb dependent) back into libdevcrypto. --- libdevcore/TrieDB.h | 1 - {libdevcore => libdevcrypto}/OverlayDB.cpp | 0 {libdevcore => libdevcrypto}/OverlayDB.h | 2 +- libethereum/CachedAddressState.cpp | 7 ++++--- libethereum/State.h | 1 + test/deprecated/main.cpp | 4 ---- 6 files changed, 6 insertions(+), 9 deletions(-) rename {libdevcore => libdevcrypto}/OverlayDB.cpp (100%) rename {libdevcore => libdevcrypto}/OverlayDB.h (97%) diff --git a/libdevcore/TrieDB.h b/libdevcore/TrieDB.h index 13a520311..f9d7bff5f 100644 --- a/libdevcore/TrieDB.h +++ b/libdevcore/TrieDB.h @@ -32,7 +32,6 @@ #include #include #include "MemoryDB.h" -#include "OverlayDB.h" #include "TrieCommon.h" namespace ldb = leveldb; diff --git a/libdevcore/OverlayDB.cpp b/libdevcrypto/OverlayDB.cpp similarity index 100% rename from libdevcore/OverlayDB.cpp rename to libdevcrypto/OverlayDB.cpp diff --git a/libdevcore/OverlayDB.h b/libdevcrypto/OverlayDB.h similarity index 97% rename from libdevcore/OverlayDB.h rename to libdevcrypto/OverlayDB.h index 2e5428bdf..b37d2c11b 100644 --- a/libdevcore/OverlayDB.h +++ b/libdevcrypto/OverlayDB.h @@ -29,7 +29,7 @@ #include #include #include -#include "MemoryDB.h" +#include namespace ldb = leveldb; namespace dev diff --git a/libethereum/CachedAddressState.cpp b/libethereum/CachedAddressState.cpp index 7c2f0a80c..757aef466 100644 --- a/libethereum/CachedAddressState.cpp +++ b/libethereum/CachedAddressState.cpp @@ -21,8 +21,9 @@ #include "CachedAddressState.h" -#include #include +#include +#include #include "Account.h" using namespace std; using namespace dev; @@ -57,8 +58,8 @@ std::unordered_map CachedAddressState::storage() const if (m_r) { SecureTrieDB memdb(const_cast(m_o), m_r[2].toHash()); // promise we won't alter the overlay! :) -// for (auto const& j: memdb) -// ret[j.first] = RLP(j.second).toInt(); + for (auto const& j: memdb) + ret[j.first] = RLP(j.second).toInt(); } if (m_s) for (auto const& j: m_s->storageOverlay()) diff --git a/libethereum/State.h b/libethereum/State.h index 971c2220a..f46d0e222 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/test/deprecated/main.cpp b/test/deprecated/main.cpp index 6cb098228..47e96f337 100644 --- a/test/deprecated/main.cpp +++ b/test/deprecated/main.cpp @@ -20,10 +20,6 @@ * Main test functions. */ -#include -#include "TrieHash.h" -#include "MemTrie.h" - #include int trieTest(); From c4df26e82ed48138e5e8cf9323467f3113bc4506 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 19 May 2015 22:15:23 +0200 Subject: [PATCH 150/157] Actually load the DAG. --- alethzero/MainWin.cpp | 2 +- ethminer/MinerAux.h | 12 ++++++------ libethcore/EthashAux.cpp | 6 +++--- libethcore/EthashAux.h | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index b59e9ce1f..a09966679 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1166,7 +1166,7 @@ void Main::on_turboMining_triggered() void Main::refreshBlockChain() { - if (!ui->blocks->isVisible()) + if (!ui->blocks->isVisible() || !isVisible()) return; DEV_TIMED_FUNCTION; diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 8e480a3ff..53a5fa7e4 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -388,7 +388,7 @@ private: (void)_m; (void)_remote; (void)_recheckPeriod; - #if ETH_JSONRPC || !ETH_TRUE +#if ETH_JSONRPC || !ETH_TRUE jsonrpc::HttpClient client(_remote); Farm rpc(client); @@ -399,7 +399,7 @@ private: f.startGPU(); ProofOfWork::WorkPackage current; - EthashAux::FullType dag; + EthashAux::FullType dag; while (true) try { @@ -418,9 +418,9 @@ private: cnote << "Getting work package..."; Json::Value v = rpc.eth_getWork(); h256 hh(v[0].asString()); - h256 newSeedHash(v[1].asString()); - if (!(dag = EthashAux::full(newSeedHash, true))) - BOOST_THROW_EXCEPTION(DAGCreationFailure()); + h256 newSeedHash(v[1].asString()); + if (!(dag = EthashAux::full(newSeedHash, true, [&](unsigned _pc){ cout << "\rCreating DAG. " << _pc << "% done..." << flush; return 0; }))) + BOOST_THROW_EXCEPTION(DAGCreationFailure()); if (hh != current.headerHash) { current.headerHash = hh; @@ -459,7 +459,7 @@ private: cerr << "JSON-RPC problem. Probably couldn't connect. Retrying in " << i << "... \r"; cerr << endl; } - #endif +#endif exit(0); } diff --git a/libethcore/EthashAux.cpp b/libethcore/EthashAux.cpp index 38425aca2..a94c1237d 100644 --- a/libethcore/EthashAux.cpp +++ b/libethcore/EthashAux.cpp @@ -167,7 +167,7 @@ EthashAux::FullType EthashAux::full(h256 const& _seedHash, bool _createIfMissing return ret; } - if (_createIfMissing || computeFull(_seedHash) == 100) + if (_createIfMissing || computeFull(_seedHash, false) == 100) { s_dagCallback = _f; cnote << "Loading from libethash..."; @@ -183,7 +183,7 @@ EthashAux::FullType EthashAux::full(h256 const& _seedHash, bool _createIfMissing #define DEV_IF_THROWS(X) try { X; } catch (...) -unsigned EthashAux::computeFull(h256 const& _seedHash) +unsigned EthashAux::computeFull(h256 const& _seedHash, bool _createIfMissing) { Guard l(get()->x_fulls); uint64_t blockNumber; @@ -199,7 +199,7 @@ unsigned EthashAux::computeFull(h256 const& _seedHash) return 100; } - if (!get()->m_fullGenerator || !get()->m_fullGenerator->joinable()) + if (_createIfMissing && (!get()->m_fullGenerator || !get()->m_fullGenerator->joinable())) { get()->m_fullProgress = 0; get()->m_generatingFullNumber = blockNumber / ETHASH_EPOCH_LENGTH * ETHASH_EPOCH_LENGTH; diff --git a/libethcore/EthashAux.h b/libethcore/EthashAux.h index b09f6465f..e6fed519f 100644 --- a/libethcore/EthashAux.h +++ b/libethcore/EthashAux.h @@ -71,7 +71,7 @@ public: static const uint64_t NotGenerating = (uint64_t)-1; /// Kicks off generation of DAG for @a _seedHash and @returns false or @returns true if ready. - static unsigned computeFull(h256 const& _seedHash); + static unsigned computeFull(h256 const& _seedHash, bool _createIfMissing = true); /// Information on the generation progress. static std::pair fullGeneratingProgress() { return std::make_pair(get()->m_generatingFullNumber, get()->m_fullProgress); } /// Kicks off generation of DAG for @a _blocknumber and blocks until ready; @returns result or empty pointer if not existing and _createIfMissing is false. From c4b044d9263b7f425a0dd8acf080f61a5d082624 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 19 May 2015 22:47:07 +0200 Subject: [PATCH 151/157] Improve AZ & eth latency. --- libethereum/BlockChain.cpp | 6 ++++-- libethereum/Client.cpp | 7 ++++++- libethereum/Client.h | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index c46127303..e23fde6b6 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -96,7 +96,7 @@ ldb::Slice dev::eth::toSlice(h256 const& _h, unsigned _sub) #endif } -#if ETH_DEBUG +#if ETH_DEBUG&&0 static const chrono::system_clock::duration c_collectionDuration = chrono::seconds(15); static const unsigned c_collectionQueueSize = 2; static const unsigned c_maxCacheSize = 1024 * 1024 * 1; @@ -318,7 +318,9 @@ tuple BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st try { // Nonce & uncle nonces already verified thread at this point. - auto r = import(block.first, block.second, _stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce & ~ImportRequirements::CheckUncles); + ImportRoute r; + DEV_TIMED_ABOVE(Block import, 500) + r = import(block.first, block.second, _stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce & ~ImportRequirements::CheckUncles); fresh += r.first; dead += r.second; } diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 97118a7a9..e39126713 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -172,6 +172,7 @@ Client::Client(p2p::Host* _extNet, std::string const& _dbPath, WithExisting _for m_preMine(m_stateDB, BaseState::CanonGenesis), m_postMine(m_stateDB) { + m_lastGetWork = std::chrono::system_clock::now() - chrono::seconds(30); m_tqReady = m_tq.onReady([=](){ this->onTransactionQueueReady(); }); // TODO: should read m_tq->onReady(thisThread, syncTransactionQueue); m_bqReady = m_bq.onReady([=](){ this->onBlockQueueReady(); }); // TODO: should read m_bq->onReady(thisThread, syncBlockQueue); m_farm.onSolutionFound([=](ProofOfWork::Solution const& s){ return this->submitWork(s); }); @@ -197,6 +198,7 @@ Client::Client(p2p::Host* _extNet, std::shared_ptr _gp, std::string c m_preMine(m_stateDB), m_postMine(m_stateDB) { + m_lastGetWork = std::chrono::system_clock::now() - chrono::seconds(30); m_tqReady = m_tq.onReady([=](){ this->onTransactionQueueReady(); }); // TODO: should read m_tq->onReady(thisThread, syncTransactionQueue); m_bqReady = m_bq.onReady([=](){ this->onBlockQueueReady(); }); // TODO: should read m_bq->onReady(thisThread, syncBlockQueue); m_farm.onSolutionFound([=](ProofOfWork::Solution const& s){ return this->submitWork(s); }); @@ -484,7 +486,7 @@ void Client::syncBlockQueue() cwork << "BQ ==> CHAIN ==> STATE"; { - tie(ir.first, ir.second, m_syncBlockQueue) = m_bc.sync(m_bq, m_stateDB, 10); + tie(ir.first, ir.second, m_syncBlockQueue) = m_bc.sync(m_bq, m_stateDB, rand() % 90 + 10); if (ir.first.empty()) return; } @@ -601,6 +603,9 @@ void Client::onChainChanged(ImportRoute const& _ir) bool Client::remoteActive() const { + cnote << chrono::duration_cast(chrono::system_clock::now().time_since_epoch()).count(); + cnote << chrono::duration_cast(m_lastGetWork.time_since_epoch()).count(); + cnote << chrono::duration_cast(chrono::system_clock::now() - m_lastGetWork).count(); return chrono::system_clock::now() - m_lastGetWork < chrono::seconds(30); } diff --git a/libethereum/Client.h b/libethereum/Client.h index 7eeb7fb2d..4fa6da8b1 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -289,7 +289,7 @@ private: BlockInfo m_miningInfo; ///< The header we're attempting to mine on (derived from m_postMine). bool remoteActive() const; ///< Is there an active and valid remote worker? bool m_remoteWorking = false; ///< Has the remote worker recently been reset? - std::chrono::system_clock::time_point m_lastGetWork = std::chrono::system_clock::time_point::min(); ///< Is there an active and valid remote worker? + std::chrono::system_clock::time_point m_lastGetWork; ///< Is there an active and valid remote worker? std::weak_ptr m_host; ///< Our Ethereum Host. Don't do anything if we can't lock. From 3c58d68fe28c9a4fd9eeb21aa432225c5e947bc7 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 19 May 2015 22:47:59 +0200 Subject: [PATCH 152/157] Quieter timing reporting. --- alethzero/MainWin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index a09966679..076e9d547 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1169,7 +1169,7 @@ void Main::refreshBlockChain() if (!ui->blocks->isVisible() || !isVisible()) return; - DEV_TIMED_FUNCTION; + DEV_TIMED_FUNCTION_ABOVE(500); cwatch << "refreshBlockChain()"; // TODO: keep the same thing highlighted. From 742f2dbcc8691581400be7ef2f5202046b5c321a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 19 May 2015 23:04:54 +0200 Subject: [PATCH 153/157] Build fix. --- libdevcore/Common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 240746302..ac4d89103 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -201,7 +201,7 @@ private: #endif #define DEV_TIMED_ABOVE(S, MS) for (::std::pair<::dev::TimerHelper, bool> __eth_t(::dev::TimerHelper(#S, MS), true); __eth_t.second; __eth_t.second = false) -#define DEV_TIMED_SCOPE_ABOVE(S) ::dev::TimerHelper __eth_t(S, MS) +#define DEV_TIMED_SCOPE_ABOVE(S, MS) ::dev::TimerHelper __eth_t(S, MS) #if WIN32 #define DEV_TIMED_FUNCTION_ABOVE(MS) DEV_TIMED_SCOPE_ABOVE(__FUNCSIG__, MS) #else From ce205f382cb1f2964f1edcbbb08e43e93bd200c9 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 19 May 2015 23:22:44 +0200 Subject: [PATCH 154/157] Remote mining fixes. --- alethzero/MainWin.cpp | 2 +- ethminer/MinerAux.h | 2 ++ libethereum/BlockQueue.h | 2 +- libethereum/Client.cpp | 8 +++++++- libethereum/Client.h | 3 +++ 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 076e9d547..4f236b3e8 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1166,7 +1166,7 @@ void Main::on_turboMining_triggered() void Main::refreshBlockChain() { - if (!ui->blocks->isVisible() || !isVisible()) + if (!ui->blocks->isVisible() && isVisible()) return; DEV_TIMED_FUNCTION_ABOVE(500); diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index 53a5fa7e4..d99e36976 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -419,6 +419,8 @@ private: Json::Value v = rpc.eth_getWork(); h256 hh(v[0].asString()); h256 newSeedHash(v[1].asString()); + if (current.seedHash != newSeedHash) + cnote << "Grabbing DAG for" << newSeedHash; if (!(dag = EthashAux::full(newSeedHash, true, [&](unsigned _pc){ cout << "\rCreating DAG. " << _pc << "% done..." << flush; return 0; }))) BOOST_THROW_EXCEPTION(DAGCreationFailure()); if (hh != current.headerHash) diff --git a/libethereum/BlockQueue.h b/libethereum/BlockQueue.h index c865bac32..d0437739d 100644 --- a/libethereum/BlockQueue.h +++ b/libethereum/BlockQueue.h @@ -94,7 +94,7 @@ public: void retryAllUnknown(); /// Get information on the items queued. - std::pair items() const { ReadGuard l(m_lock); return std::make_pair(m_verified.size(), m_unknown.size()); } + std::pair items() const { ReadGuard l(m_lock); return std::make_pair(m_readySet.size(), m_unknownSet.size()); } /// Clear everything. void clear() { WriteGuard l(m_lock); DEV_INVARIANT_CHECK; Guard l2(m_verification); m_readySet.clear(); m_drainingSet.clear(); m_verified.clear(); m_unverified.clear(); m_unknownSet.clear(); m_unknown.clear(); m_future.clear(); } diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index e39126713..0fd27520d 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -455,8 +455,13 @@ ProofOfWork::WorkPackage Client::getWork() { // lock the work so a later submission isn't invalidated by processing a transaction elsewhere. // this will be reset as soon as a new block arrives, allowing more transactions to be processed. + bool oldShould = shouldServeWork(); m_lastGetWork = chrono::system_clock::now(); m_remoteWorking = true; + + // if this request has made us bother to serve work, prep it now. + if (!oldShould && shouldServeWork()) + onPostStateChanged(); return ProofOfWork::package(m_miningInfo); } @@ -612,7 +617,8 @@ bool Client::remoteActive() const void Client::onPostStateChanged() { cnote << "Post state changed"; - if (isMining() || remoteActive()) + + if (m_bq.items().first == 0 && (isMining() || remoteActive())) { cnote << "Restarting mining..."; DEV_WRITE_GUARDED(x_working) diff --git a/libethereum/Client.h b/libethereum/Client.h index 4fa6da8b1..c77cb6034 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -274,6 +274,9 @@ private: /// Ticks various system-level objects. void tick(); + /// @returns true only if it's worth bothering to prep the mining block. + bool shouldServeWork() const { return m_bq.items().first == 0 && (isMining() || remoteActive()); } + VersionChecker m_vc; ///< Dummy object to check & update the protocol version. CanonBlockChain m_bc; ///< Maintains block database. BlockQueue m_bq; ///< Maintains a list of incoming blocks not yet on the blockchain (to be imported). From cfb9bd15b02e0d7c914cb00b8216d44089b11b37 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 19 May 2015 23:29:13 +0200 Subject: [PATCH 155/157] Tidy up notifications. --- alethzero/MainWin.cpp | 2 +- libethcore/Miner.h | 10 ++++------ libethereum/Client.cpp | 5 +---- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 4f236b3e8..07f48c0bc 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1353,7 +1353,7 @@ void Main::timerEvent(QTimerEvent*) auto ls = ethereum()->checkWatchSafe(i.first); if (ls.size()) { - cnote << "FIRING WATCH" << i.first << ls.size(); +// cnote << "FIRING WATCH" << i.first << ls.size(); i.second(ls); } } diff --git a/libethcore/Miner.h b/libethcore/Miner.h index 3a68491ff..cede34475 100644 --- a/libethcore/Miner.h +++ b/libethcore/Miner.h @@ -107,12 +107,10 @@ public: } if (!!_work) { - boost::timer t; - pause(); - cdebug << "pause took" << t.elapsed(); - t.restart(); - kickOff(); - cdebug << "kickOff took" << t.elapsed(); + DEV_TIMED_ABOVE(pause, 250) + pause(); + DEV_TIMED_ABOVE(kickOff, 250) + kickOff(); } else if (!_work && !!old) pause(); diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 0fd27520d..f10eda55a 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -608,9 +608,6 @@ void Client::onChainChanged(ImportRoute const& _ir) bool Client::remoteActive() const { - cnote << chrono::duration_cast(chrono::system_clock::now().time_since_epoch()).count(); - cnote << chrono::duration_cast(m_lastGetWork.time_since_epoch()).count(); - cnote << chrono::duration_cast(chrono::system_clock::now() - m_lastGetWork).count(); return chrono::system_clock::now() - m_lastGetWork < chrono::seconds(30); } @@ -647,7 +644,7 @@ void Client::noteChanged(h256Hash const& _filters) { Guard l(x_filtersWatches); if (_filters.size()) - filtersStreamOut(cnote << "noteChanged:", _filters); + filtersStreamOut(cwatch << "noteChanged:", _filters); // accrue all changes left in each filter into the watches. for (auto& w: m_watches) if (_filters.count(w.second.id)) From 846de9aceaca7fae862c2fbe7b6fb5612e80a5b2 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 20 May 2015 09:31:38 +0200 Subject: [PATCH 156/157] Pregenerate DAG when mining on AZ/eth/ethminer. Use regeneratable key for decrets by default. --- ethminer/MinerAux.h | 9 ++++++++- libethcore/Ethash.cpp | 8 ++++++++ libethcore/Ethash.h | 1 + libethereum/Client.cpp | 6 +++++- libethereum/Executive.cpp | 36 ++++++++++++++++++++++++++++++++++++ libethereum/Executive.h | 1 + libethereum/ExtVM.cpp | 10 +++++----- libethereum/ExtVM.h | 2 +- libethereum/KeyManager.cpp | 3 +++ libethereum/KeyManager.h | 10 ++++++++-- libevm/ExtVMFace.h | 14 +++++++++++++- libevm/VM.cpp | 26 +++++++++++++++++++------- test/libevm/vm.cpp | 7 ++----- test/libevm/vm.h | 2 +- 14 files changed, 111 insertions(+), 24 deletions(-) diff --git a/ethminer/MinerAux.h b/ethminer/MinerAux.h index d99e36976..ef0621b7f 100644 --- a/ethminer/MinerAux.h +++ b/ethminer/MinerAux.h @@ -174,6 +174,10 @@ public: m_minerType = MinerType::GPU; miningThreads = 1; } + else if (arg == "--no-precompute") + { + precompute = false; + } else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc) { string m = boost::to_lower_copy(string(argv[++i])); @@ -268,6 +272,7 @@ public: << "Work farming mode:" << endl << " -F,--farm Put into mining farm mode with the work server at URL (default: http://127.0.0.1:8545)" << endl << " --farm-recheck Leave n ms between checks for changed work (default: 500)." << endl + << " --no-precompute Don't precompute the next epoch's DAG." << endl #endif << "Ethash verify mode:" << endl << " -w,--check-pow Check PoW credentials for validity." << endl @@ -423,6 +428,8 @@ private: cnote << "Grabbing DAG for" << newSeedHash; if (!(dag = EthashAux::full(newSeedHash, true, [&](unsigned _pc){ cout << "\rCreating DAG. " << _pc << "% done..." << flush; return 0; }))) BOOST_THROW_EXCEPTION(DAGCreationFailure()); + if (precompute) + EthashAux::computeFull(sha3(newSeedHash), true); if (hh != current.headerHash) { current.headerHash = hh; @@ -486,5 +493,5 @@ private: /// Farm params string farmURL = "http://127.0.0.1:8545"; unsigned farmRecheckPeriod = 500; - + bool precompute = true; }; diff --git a/libethcore/Ethash.cpp b/libethcore/Ethash.cpp index 1f16166f0..228f03f8e 100644 --- a/libethcore/Ethash.cpp +++ b/libethcore/Ethash.cpp @@ -75,6 +75,13 @@ Ethash::WorkPackage Ethash::package(BlockInfo const& _bi) return ret; } +void Ethash::ensurePrecomputed(unsigned _number) +{ + if (_number % ETHASH_EPOCH_LENGTH > ETHASH_EPOCH_LENGTH * 9 / 10) + // 90% of the way to the new epoch + EthashAux::computeFull(EthashAux::seedHash(_number + ETHASH_EPOCH_LENGTH), true); +} + void Ethash::prep(BlockInfo const& _header, std::function const& _f) { EthashAux::full(_header.seedHash(), true, _f); @@ -306,6 +313,7 @@ void Ethash::GPUMiner::workLoop() cnote << "workLoop" << !!m_miner << m_minerSeed << w.seedHash; if (!m_miner || m_minerSeed != w.seedHash) { + cnote << "Initialising miner..."; m_minerSeed = w.seedHash; delete m_miner; diff --git a/libethcore/Ethash.h b/libethcore/Ethash.h index 81f842e4f..86540678f 100644 --- a/libethcore/Ethash.h +++ b/libethcore/Ethash.h @@ -74,6 +74,7 @@ public: static std::string name(); static unsigned revision(); static void prep(BlockInfo const& _header, std::function const& _f = std::function()); + static void ensurePrecomputed(unsigned _number); static bool verify(BlockInfo const& _header); static bool preVerify(BlockInfo const& _header); static WorkPackage package(BlockInfo const& _header); diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index f10eda55a..e372e611a 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -457,11 +457,13 @@ ProofOfWork::WorkPackage Client::getWork() // this will be reset as soon as a new block arrives, allowing more transactions to be processed. bool oldShould = shouldServeWork(); m_lastGetWork = chrono::system_clock::now(); - m_remoteWorking = true; // if this request has made us bother to serve work, prep it now. if (!oldShould && shouldServeWork()) onPostStateChanged(); + else + // otherwise, set this to true so that it gets prepped next time. + m_remoteWorking = true; return ProofOfWork::package(m_miningInfo); } @@ -627,6 +629,8 @@ void Client::onPostStateChanged() m_miningInfo = m_postMine.info(); } m_farm.setWork(m_miningInfo); + + Ethash::ensurePrecomputed(m_bc.number()); } m_remoteWorking = false; } diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index a1eee9440..4fbf51244 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -159,6 +159,42 @@ bool Executive::call(Address _receiveAddress, Address _codeAddress, Address _sen return !m_ext; } +bool Executive::call(CallParameters const& _p, u256 const& _gasPrice, Address const& _origin) +{ + m_isCreation = false; +// cnote << "Transferring" << formatBalance(_value) << "to receiver."; + auto it = !(_p.codeAddress & ~h160(0xffffffff)) ? precompiled().find((unsigned)(u160)_p.codeAddress) : precompiled().end(); + if (it != precompiled().end()) + { + bigint g = it->second.gas(_p.data); + if (_p.gas < g) + { + m_endGas = 0; + m_excepted = TransactionException::OutOfGasBase; + // Bail from exception. + return true; // true actually means "all finished - nothing more to be done regarding go(). + } + else + { + m_endGas = (u256)(_p.gas - g); + m_precompiledOut = it->second.exec(_p.data); + m_out = &m_precompiledOut; + } + } + else if (m_s.addressHasCode(_p.codeAddress)) + { + m_vm = VMFactory::create(_p.gas); + bytes const& c = m_s.code(_p.codeAddress); + m_ext = make_shared(m_s, m_lastHashes, _p.receiveAddress, _p.senderAddress, _origin, _p.value, _gasPrice, _p.data, &c, m_depth); + } + else + m_endGas = _p.gas; + + m_s.transferBalance(_p.senderAddress, _p.receiveAddress, _p.value); + + return !m_ext; +} + bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _init, Address _origin) { m_isCreation = true; diff --git a/libethereum/Executive.h b/libethereum/Executive.h index 3806221be..8bb0ab771 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -95,6 +95,7 @@ public: /// Set up the executive for evaluating a bare CALL (message call) operation. /// @returns false iff go() must be called (and thus a VM execution in required). bool call(Address _myAddress, Address _codeAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256 _gas, Address _originAddress); + bool call(CallParameters const& _cp, u256 const& _gasPrice, Address const& _origin); /// Finalise an operation through accruing the substate into the parent context. void accrueSubState(SubState& _parentContext); diff --git a/libethereum/ExtVM.cpp b/libethereum/ExtVM.cpp index 68d146ce1..c0591cef5 100644 --- a/libethereum/ExtVM.cpp +++ b/libethereum/ExtVM.cpp @@ -26,16 +26,16 @@ using namespace std; using namespace dev; using namespace dev::eth; -bool ExtVM::call(Address _receiveAddress, u256 _txValue, bytesConstRef _txData, u256& io_gas, bytesRef _out, OnOpFunc const& _onOp, Address _myAddressOverride, Address _codeAddressOverride) +bool ExtVM::call(CallParameters& _p) { Executive e(m_s, lastHashes, depth + 1); - if (!e.call(_receiveAddress, _codeAddressOverride, _myAddressOverride ? _myAddressOverride : myAddress, _txValue, gasPrice, _txData, io_gas, origin)) + if (!e.call(_p, gasPrice, origin)) { - e.go(_onOp); + e.go(_p.onOp); e.accrueSubState(sub); } - io_gas = e.endGas(); - e.out().copyTo(_out); + _p.gas = e.endGas(); + e.out().copyTo(_p.out); return !e.excepted(); } diff --git a/libethereum/ExtVM.h b/libethereum/ExtVM.h index 1a2d180dd..babff4edf 100644 --- a/libethereum/ExtVM.h +++ b/libethereum/ExtVM.h @@ -58,7 +58,7 @@ public: virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc const& _onOp = {}) override final; /// Create a new message call. Leave _myAddressOverride as the default to use the present address as caller. - virtual bool call(Address _receiveAddress, u256 _txValue, bytesConstRef _txData, u256& io_gas, bytesRef _out, OnOpFunc const& _onOp = {}, Address _myAddressOverride = {}, Address _codeAddressOverride = {}) override final; + virtual bool call(CallParameters& _params) override final; /// Read address's balance. virtual u256 balance(Address _a) override final { return m_s.balance(_a); } diff --git a/libethereum/KeyManager.cpp b/libethereum/KeyManager.cpp index cba6f4325..8c3fd28c3 100644 --- a/libethereum/KeyManager.cpp +++ b/libethereum/KeyManager.cpp @@ -71,6 +71,7 @@ bool KeyManager::load(std::string const& _pass) m_password = (string)s[3]; } m_cachedPasswords[hashPassword(m_password)] = m_password; + m_cachedPasswords[hashPassword(defaultPassword())] = defaultPassword(); return true; } catch (...) { @@ -214,4 +215,6 @@ void KeyManager::write(h128 const& _key, std::string const& _keysFile) const writeFile(_keysFile, encryptSymNoAuth(_key, h128(), &s.out())); m_key = _key; + m_cachedPasswords[hashPassword(defaultPassword())] = defaultPassword(); + } diff --git a/libethereum/KeyManager.h b/libethereum/KeyManager.h index bb537e1f1..0a83fcc00 100644 --- a/libethereum/KeyManager.h +++ b/libethereum/KeyManager.h @@ -75,10 +75,11 @@ public: 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()); } + h128 import(Secret const& _s, std::string const& _info) { return import(_s, _info, defaultPassword(), std::string()); } SecretStore& store() { return m_store; } void importExisting(h128 const& _uuid, std::string const& _info, std::string const& _pass, std::string const& _passInfo); + void importExisting(h128 const& _uuid, std::string const& _info) { importExisting(_uuid, _info, defaultPassword(), std::string()); } Secret secret(Address const& _address, std::function const& _pass = DontKnowThrow) const; Secret secret(h128 const& _uuid, std::function const& _pass = DontKnowThrow) const; @@ -87,6 +88,7 @@ public: void kill(Address const& _a); private: + std::string defaultPassword() const { return asString(m_key.ref()); } h256 hashPassword(std::string const& _pass) const; // Only use if previously loaded ok. @@ -103,7 +105,11 @@ private: // Passwords that we're storing. mutable std::unordered_map m_cachedPasswords; - // The default password for keys in the keystore - protected by the master password. + // DEPRECATED. + // Used to be the default password for keys in the keystore, stored in the keys file. + // Now the default password is based off the key of the keys file directly, so this is redundant + // except for the fact that people have existing keys stored with it. Leave for now until/unless + // we have an upgrade strategy. std::string m_password; SecretStore m_store; diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 8ebfd8fa5..ce259bef2 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -108,6 +108,18 @@ using LastHashes = std::vector; using OnOpFunc = std::function; +struct CallParameters +{ + Address senderAddress; + Address codeAddress; + Address receiveAddress; + u256 gas; + u256 value; + bytesConstRef data; + bytesRef out; + OnOpFunc onOp; +}; + /** * @brief Interface and null implementation of the class for specifying VM externalities. */ @@ -153,7 +165,7 @@ public: virtual h160 create(u256, u256&, bytesConstRef, OnOpFunc const&) { return h160(); } /// Make a new message call. - virtual bool call(Address, u256, bytesConstRef, u256&, bytesRef, OnOpFunc const&, Address, Address) { return false; } + virtual bool call(CallParameters&) { return false; } /// Revert any changes made (by any of the other calls). virtual void log(h256s&& _topics, bytesConstRef _data) { sub.logs.push_back(LogEntry(myAddress, std::move(_topics), _data.toBytes())); } diff --git a/libevm/VM.cpp b/libevm/VM.cpp index 368d27389..27650e3ad 100644 --- a/libevm/VM.cpp +++ b/libevm/VM.cpp @@ -56,6 +56,8 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) { m_stack.reserve((unsigned)c_stackLimit); + unique_ptr callParams; + static const array c_metrics = metrics(); auto memNeed = [](u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; }; @@ -626,13 +628,16 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) case Instruction::CALL: case Instruction::CALLCODE: { - u256 gas = m_stack.back(); + if (!callParams) + callParams.reset(new CallParameters); + + callParams->gas = m_stack.back(); if (m_stack[m_stack.size() - 3] > 0) - gas += c_callStipend; + callParams->gas += c_callStipend; m_stack.pop_back(); - Address receiveAddress = asAddress(m_stack.back()); + callParams->receiveAddress = asAddress(m_stack.back()); m_stack.pop_back(); - u256 value = m_stack.back(); + callParams->value = m_stack.back(); m_stack.pop_back(); unsigned inOff = (unsigned)m_stack.back(); @@ -644,12 +649,19 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) unsigned outSize = (unsigned)m_stack.back(); m_stack.pop_back(); - if (_ext.balance(_ext.myAddress) >= value && _ext.depth < 1024) - m_stack.push_back(_ext.call(inst == Instruction::CALL ? receiveAddress : _ext.myAddress, value, bytesConstRef(m_temp.data() + inOff, inSize), gas, bytesRef(m_temp.data() + outOff, outSize), _onOp, {}, receiveAddress)); + if (_ext.balance(_ext.myAddress) >= callParams->value && _ext.depth < 1024) + { + callParams->onOp = _onOp; + callParams->senderAddress = _ext.myAddress; + callParams->codeAddress = inst == Instruction::CALL ? callParams->receiveAddress : callParams->senderAddress; + callParams->data = bytesConstRef(m_temp.data() + inOff, inSize); + callParams->out = bytesRef(m_temp.data() + outOff, outSize); + m_stack.push_back(_ext.call(*callParams)); + } else m_stack.push_back(0); - m_gas += gas; + m_gas += callParams->gas; break; } case Instruction::RETURN: diff --git a/test/libevm/vm.cpp b/test/libevm/vm.cpp index 10670bfe3..bda751af4 100644 --- a/test/libevm/vm.cpp +++ b/test/libevm/vm.cpp @@ -44,13 +44,10 @@ h160 FakeExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _init, OnOpF return na; } -bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256& io_gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride, Address _codeAddressOverride) +bool FakeExtVM::call(CallParameters& _p) { - Transaction t(_value, gasPrice, io_gas, _receiveAddress, _data.toVector()); + Transaction t(_p.value, gasPrice, _p.gas, _p.receiveAddress, _p.data.toVector()); callcreates.push_back(t); - (void)_out; - (void)_myAddressOverride; - (void)_codeAddressOverride; return true; } diff --git a/test/libevm/vm.h b/test/libevm/vm.h index dff89d98d..18fa1ca25 100644 --- a/test/libevm/vm.h +++ b/test/libevm/vm.h @@ -59,7 +59,7 @@ public: virtual void suicide(Address _a) override { std::get<0>(addresses[_a]) += std::get<0>(addresses[myAddress]); addresses.erase(myAddress); } virtual bytes const& codeAt(Address _a) override { return std::get<3>(addresses[_a]); } virtual h160 create(u256 _endowment, u256& io_gas, bytesConstRef _init, eth::OnOpFunc const&) override; - virtual bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256& io_gas, bytesRef _out, eth::OnOpFunc const&, Address, Address) override; + virtual bool call(eth::CallParameters&) override; void setTransaction(Address _caller, u256 _value, u256 _gasPrice, bytes const& _data); void setContract(Address _myAddress, u256 _myBalance, u256 _myNonce, std::map const& _storage, bytes const& _code); void set(Address _a, u256 _myBalance, u256 _myNonce, std::map const& _storage, bytes const& _code); From 32a850a9ff42d775f0d0ee0868db88f4f748504d Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 20 May 2015 09:59:18 +0200 Subject: [PATCH 157/157] Trie timing. --- exp/main.cpp | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/exp/main.cpp b/exp/main.cpp index d31306496..47efe576a 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -34,6 +34,9 @@ #include #include #include +#include +#include +/* #include #include #include @@ -41,7 +44,6 @@ #include #include #include -#include #include #include #include @@ -55,17 +57,43 @@ #include #include #include -#include +#include */ using namespace std; using namespace dev; -using namespace dev::eth; +/*using namespace dev::eth; using namespace dev::p2p; using namespace dev::shh; namespace js = json_spirit; namespace fs = boost::filesystem; - +*/ #if 1 +int main() +{ + cdebug << "EXP"; + vector data; + for (unsigned i = 0; i < 10000; ++i) + data.push_back(rlp(i)); + + h256 ret; + DEV_TIMED(triedb) + { + MemoryDB mdb; + GenericTrieDB t(&mdb); + t.init(); + unsigned i = 0; + for (auto const& d: data) + t.insert(rlp(i++), d); + ret = t.root(); + } + cdebug << ret; + DEV_TIMED(hash256) + ret = orderedTrieRoot(data); + cdebug << ret; +} + +#elif 0 + int main() { KeyManager keyman;