From fef4ed9f154b169e43571e4d2e2a50efa0a8e105 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 28 Feb 2015 00:32:02 +0100 Subject: [PATCH 01/54] Warnings fixes. --- alethzero/MainWin.cpp | 9 +++++++-- libwhisper/WhisperHost.cpp | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 9ee3f36e3..a4c8a7b60 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1382,11 +1382,16 @@ void Main::on_blocks_currentItemChanged() s << "
Pre: " << BlockInfo(ethereum()->blockChain().block(info.parentHash)).stateRoot << ""; else s << "
Pre: Nothing is before Phil"; + BlockReceipts receipts = ethereum()->blockChain().receipts(h); + unsigned ii = 0; for (auto const& i: block[1]) - s << "
" << sha3(i.data()).abridged();// << ": " << i[1].toHash() << " [" << i[2].toInt() << " used]"; + { + s << "
" << sha3(i.data()).abridged() << ": " << receipts.receipts[ii].stateRoot() << " [" << receipts.receipts[ii].gasUsed() << " used]"; + ++ii; + } s << "
Post: " << info.stateRoot << ""; s << "
Dump: " Span(Mono) << toHex(block[0].data()) << ""; - s << "
Receipts-Hex: " Span(Mono) << toHex(ethereum()->blockChain().receipts(h).rlp()) << "
"; + s << "
Receipts-Hex: " Span(Mono) << toHex(receipts.rlp()) << "
"; } else { diff --git a/libwhisper/WhisperHost.cpp b/libwhisper/WhisperHost.cpp index 22a6a56fe..633eef5b5 100644 --- a/libwhisper/WhisperHost.cpp +++ b/libwhisper/WhisperHost.cpp @@ -58,7 +58,7 @@ void WhisperHost::inject(Envelope const& _m, WhisperPeer* _p) { cnote << this << ": inject: " << _m.expiry() << _m.ttl() << _m.topic() << toHex(_m.data()); - if (_m.expiry() <= time(0)) + if (_m.expiry() <= (unsigned)time(0)) return; auto h = _m.sha3(); @@ -171,7 +171,7 @@ void WhisperHost::cleanup() { // remove old messages. // should be called every now and again. - auto now = time(0); + unsigned now = (unsigned)time(0); WriteGuard l(x_messages); for (auto it = m_expiryQueue.begin(); it != m_expiryQueue.end() && it->first <= now; it = m_expiryQueue.erase(it)) m_messages.erase(it->second); From 97fc7305dcf098ccd166c4aa66f798b0c8917768 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Sun, 1 Mar 2015 19:09:01 +0100 Subject: [PATCH 02/54] transaction hash in event logs, second approach --- libethereum/Client.cpp | 28 +++++++++++++++-------- libethereum/Client.h | 4 ++-- libevm/ExtVMFace.h | 3 ++- libweb3jsonrpc/WebThreeStubServerBase.cpp | 1 + 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 5ea513f0a..02412f4c1 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -291,7 +291,7 @@ LocalisedLogEntries Client::checkWatch(unsigned _watchId) return ret; } -void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed) +void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed, h256 _sha3) { Guard l(m_filterLock); for (pair& i: m_filters) @@ -303,7 +303,7 @@ void Client::appendFromNewPending(TransactionReceipt const& _receipt, h256Set& i { // filter catches them for (LogEntry const& l: m) - i.second.changes.push_back(LocalisedLogEntry(l, m_bc.number() + 1)); + i.second.changes.push_back(LocalisedLogEntry(l, m_bc.number() + 1, _sha3)); io_changed.insert(i.first); } } @@ -319,14 +319,16 @@ void Client::appendFromNewBlock(h256 const& _block, h256Set& io_changed) for (pair& i: m_filters) if ((unsigned)i.second.filter.latest() >= d.number && (unsigned)i.second.filter.earliest() <= d.number && i.second.filter.matches(d.logBloom)) // acceptable number & looks like block may contain a matching log entry. - for (TransactionReceipt const& tr: br.receipts) + for (size_t j = 0; j < br.receipts.size(); j++) { + auto tr = br.receipts[j]; auto m = i.second.filter.matches(tr); if (m.size()) { + auto sha3 = transaction(d.hash, j).sha3(); // filter catches them for (LogEntry const& l: m) - i.second.changes.push_back(LocalisedLogEntry(l, (unsigned)d.number)); + i.second.changes.push_back(LocalisedLogEntry(l, (unsigned)d.number, sha3)); io_changed.insert(i.first); } } @@ -582,8 +584,9 @@ void Client::doWork() TransactionReceipts newPendingReceipts = m_postMine.sync(m_bc, m_tq); if (newPendingReceipts.size()) { - for (auto i: newPendingReceipts) - appendFromNewPending(i, changeds); + for (size_t i = 0; i < newPendingReceipts.size(); i++) + appendFromNewPending(newPendingReceipts[i], changeds, m_postMine.pending()[i].sha3()); + changeds.insert(PendingChangedFilter); if (isMining()) @@ -756,6 +759,7 @@ LocalisedLogEntries Client::logs(LogFilter const& _f) const { // Might have a transaction that contains a matching log. TransactionReceipt const& tr = m_postMine.receipt(i); + auto sha3 = m_postMine.pending()[i].sha3(); LogEntries le = _f.matches(tr); if (le.size()) { @@ -763,7 +767,7 @@ LocalisedLogEntries Client::logs(LogFilter const& _f) const if (s) s--; else - ret.insert(ret.begin(), LocalisedLogEntry(le[j], begin)); + ret.insert(ret.begin(), LocalisedLogEntry(le[j], begin, sha3)); } } begin = m_bc.number(); @@ -782,11 +786,15 @@ LocalisedLogEntries Client::logs(LogFilter const& _f) const int total = 0; #endif // check block bloom - if (_f.matches(m_bc.info(h).logBloom)) - for (TransactionReceipt receipt: m_bc.receipts(h).receipts) + auto info = m_bc.info(h); + auto receipts = m_bc.receipts(h).receipts; + if (_f.matches(info.logBloom)) + for (size_t i = 0; i < receipts.size(); i++) { + TransactionReceipt receipt = receipts[i]; if (_f.matches(receipt.bloom())) { + auto sha3 = transaction(info.hash, i).sha3(); LogEntries le = _f.matches(receipt); if (le.size()) { @@ -798,7 +806,7 @@ LocalisedLogEntries Client::logs(LogFilter const& _f) const if (s) s--; else - ret.insert(ret.begin(), LocalisedLogEntry(le[j], n)); + ret.insert(ret.begin(), LocalisedLogEntry(le[j], n, sha3)); } } } diff --git a/libethereum/Client.h b/libethereum/Client.h index 7cd520ab6..c689363b3 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -220,7 +220,7 @@ public: /// @returns the length of the chain. virtual unsigned number() const { return m_bc.number(); } - /// Get a map containing each of the pending transactions. + /// Get the list of pending transactions. /// @TODO: Remove in favour of transactions(). virtual Transactions pending() const { return m_postMine.pending(); } @@ -311,7 +311,7 @@ public: protected: /// Collate the changed filters for the bloom filter of the given pending transaction. /// Insert any filters that are activated into @a o_changed. - void appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed); + void appendFromNewPending(TransactionReceipt const& _receipt, h256Set& io_changed, h256 _sha3); /// Collate the changed filters for the hash of the given block. /// Insert any filters that are activated into @a o_changed. diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 13e8712b8..95910d7cb 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -63,9 +63,10 @@ using LogEntries = std::vector; struct LocalisedLogEntry: public LogEntry { LocalisedLogEntry() {} - LocalisedLogEntry(LogEntry const& _le, unsigned _number): LogEntry(_le), number(_number) {} + LocalisedLogEntry(LogEntry const& _le, unsigned _number, h256 _sha3 = h256(u256(0))): LogEntry(_le), number(_number), sha3(_sha3) {} unsigned number = 0; + h256 sha3; }; using LocalisedLogEntries = std::vector; diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index dbf3b2ec9..6e0db8b47 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -95,6 +95,7 @@ static Json::Value toJson(dev::eth::LocalisedLogEntry const& _e) for (auto const& t: _e.topics) res["topic"].append(toJS(t)); res["number"] = _e.number; + res["hash"] = toJS(_e.sha3); return res; } From 8828c64c217b85bcb9abb2a2df2753ed0f1d32c2 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 2 Mar 2015 15:22:15 +0100 Subject: [PATCH 03/54] - Accounts Managements --- mix/ClientModel.cpp | 26 +++++++++++-- mix/ClientModel.h | 2 + mix/MixClient.cpp | 6 +-- mix/qml/StateDialog.qml | 77 +++++++++++++++++++++++++++++++++----- mix/qml/StateListModel.qml | 13 +++++-- 5 files changed, 102 insertions(+), 22 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 5c36ef716..11a34c211 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -47,6 +47,8 @@ namespace dev namespace mix { +//const Secret c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); + class RpcConnector: public jsonrpc::AbstractServerConnector { public: @@ -136,6 +138,15 @@ void ClientModel::mine() }); } +QString ClientModel::newAddress() const +{ + KeyPair a = KeyPair.create(); + return toHex(a.secret().ref()); + //m_client.addBalance(a.address(), _balance, 0); + //emit accountCreated; + //return QString::fromStdString(toHex(a.address().ref())); +} + QVariantMap ClientModel::contractAddresses() const { QVariantMap res; @@ -151,7 +162,7 @@ void ClientModel::debugDeployment() void ClientModel::setupState(QVariantMap _state) { - u256 balance = (qvariant_cast(_state.value("balance")))->toU256Wei(); + QVariantList balances = _state.value("balances").toList(); QVariantList transactions = _state.value("transactions").toList(); std::vector transactionSequence; @@ -194,10 +205,10 @@ void ClientModel::setupState(QVariantMap _state) transactionSequence.push_back(transactionSettings); } } - executeSequence(transactionSequence, balance); + executeSequence(transactionSequence, balances); } -void ClientModel::executeSequence(std::vector const& _sequence, u256 _balance) +void ClientModel::executeSequence(std::vector const& _sequence, QVariantList _balances) { if (m_running) BOOST_THROW_EXCEPTION(ExecutionStateException()); @@ -211,7 +222,14 @@ void ClientModel::executeSequence(std::vector const& _seque { try { - m_client->resetState(_balance); + std::map balancesMap; + for (auto b: _balances) + { + QVariantMap address = b.toMap(); + balancesMap.insert(std::make_pair(KeyPair(Secret(address.value("Secret").toString())).address(), Account(address.value("Balance").toString(), Account::NormalCreation))); + } + + m_client->resetState(balancesMap); onStateReset(); for (TransactionSettings const& transaction: _sequence) { diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 60a70a065..8cb79cca2 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -27,6 +27,7 @@ #include #include #include +#include "QBigInt.h" #include "MachineStates.h" namespace dev @@ -151,6 +152,7 @@ public slots: Q_INVOKABLE void debugRecord(unsigned _index); /// Show the debugger for an empty record Q_INVOKABLE void emptyRecord(); + Q_INVOKABLE QString newAddress(); private slots: /// Update UI with machine states result. Display a modal dialog. diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 9a89c1c25..d1ef36e41 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -40,7 +40,6 @@ namespace dev namespace mix { -const Secret c_userAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); const u256 c_mixGenesisDifficulty = (u256) 1 << 4; class MixBlockChain: public dev::eth::BlockChain @@ -71,7 +70,7 @@ MixClient::~MixClient() { } -void MixClient::resetState(u256 _balance) +void MixClient::resetState(std::map _genesisState) { WriteGuard l(x_state); Guard fl(m_filterLock); @@ -81,8 +80,7 @@ void MixClient::resetState(u256 _balance) m_stateDB = OverlayDB(); TrieDB accountState(&m_stateDB); accountState.init(); - std::map genesisState = { std::make_pair(KeyPair(c_userAccountSecret).address(), Account(_balance, Account::NormalCreation)) }; - dev::eth::commit(genesisState, static_cast(m_stateDB), accountState); + dev::eth::commit(_genesisState, static_cast(m_stateDB), accountState); h256 stateRoot = accountState.root(); m_bc.reset(); m_bc.reset(new MixBlockChain(m_dbPath, stateRoot)); diff --git a/mix/qml/StateDialog.qml b/mix/qml/StateDialog.qml index abb045497..b63a7e178 100644 --- a/mix/qml/StateDialog.qml +++ b/mix/qml/StateDialog.qml @@ -19,16 +19,17 @@ Window { color: StateDialogStyle.generic.backgroundColor property alias stateTitle: titleField.text - property alias stateBalance: balanceField.value + //property alias stateBalance: balanceField.value property alias isDefault: defaultCheckBox.checked property int stateIndex property var stateTransactions: [] + property var stateAccounts: [] signal accepted function open(index, item, setDefault) { stateIndex = index; stateTitle = item.title; - balanceField.value = item.balance; + //balanceField.value = item.balance; transactionsModel.clear(); stateTransactions = []; var transactions = item.transactions; @@ -37,6 +38,13 @@ Window { stateTransactions.push(item.transactions[t]); } + stateAccounts = []; + for (var k = 0; k < item.accounts; k++) + { + accountsModel.append(item.accounts[k]); + stateAccounts.push(item.accounts[k]); + } + modalStateDialog.setX((Screen.width - width) / 2); modalStateDialog.setY((Screen.height - height) / 2); @@ -54,10 +62,12 @@ Window { function getItem() { var item = { title: stateDialog.stateTitle, - balance: stateDialog.stateBalance, - transactions: [] + //balance: stateDialog.stateBalance, + transactions: [], + accounts: [] } item.transactions = stateTransactions; + item.accounts = stateAccounts; return item; } @@ -92,13 +102,44 @@ Window { Layout.fillWidth: true DefaultLabel { Layout.preferredWidth: 75 - text: qsTr("Balance") + text: qsTr("Accounts") } - Ether { - id: balanceField - edit: true - displayFormattedValue: true - Layout.fillWidth: true + + Rectangle + { + Button { + text: "add new accounts" + onClicked: accountsModel.newAccount("10000", QEther.Ether); + } + } + + TableView + { + model: accountsModel + TableViewColumn { + role: "secret" + title: qsTr("Address") + width: 100 + delegate: Item { + DefaultLabel { + text: styleData.value + } + } + } + + TableViewColumn { + role: "balance" + title: qsTr("Balance") + width: 200 + delegate: Item { + Ether { + id: balanceField + edit: true + displayFormattedValue: true + value: styleData.value + } + } + } } } @@ -196,6 +237,22 @@ Window { } } + ListModel { + id: accountsModel + + function newAccount(_balance, _unit) + { + accountsModel.append({ secret: _secret, balance: QEtherHelper.createEther(_balance, _unit) }); + stateAccounts.push({ secret: _secret, balance: QEtherHelper.createEther(_balance, _unit) }); + } + + function removeAccount(_i) + { + accountsModel.remove(_i); + stateAccounts.splice(_i, 1); + } + } + ListModel { id: transactionsModel diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index 52b0d542d..640ddfe96 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -152,7 +152,7 @@ Item { ListModel { id: stateListModel - + property string defaultSecret: "cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074" property int defaultStateIndex: 0 signal defaultStateChanged; signal stateListModelReady; @@ -168,14 +168,18 @@ Item { } function createDefaultState() { - //var ether = QEtherHelper.createEther("100000000000000000000000000", QEther.Wei); var ether = QEtherHelper.createEther("1000000", QEther.Ether); var item = { title: "", - balance: ether, - transactions: [] + transactions: [], + accounts: [] }; + item.accounts.push({ + secret: defaultSecret, + balance: ether + }); + //add all stdc contracts for (var i = 0; i < contractLibrary.model.count; i++) { var contractTransaction = defaultTransactionItem(); @@ -194,6 +198,7 @@ Item { ctorTr.contractId = c; item.transactions.push(ctorTr); } + return item; } From abcb3ee832eb48b1938cd7c5079750c82f7dafc4 Mon Sep 17 00:00:00 2001 From: sveneh Date: Mon, 2 Mar 2015 15:39:04 +0100 Subject: [PATCH 04/54] updated to the latest develop build with jit support --- docker/Dockerfile | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 9c76549cb..d0a35a078 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -8,23 +8,29 @@ RUN apt-get upgrade -y RUN apt-get install -qy build-essential g++-4.8 git cmake libboost-all-dev libcurl4-openssl-dev wget RUN apt-get install -qy automake unzip libgmp-dev libtool libleveldb-dev yasm libminiupnpc-dev libreadline-dev scons RUN apt-get install -qy libjsoncpp-dev libargtable2-dev - -# NCurses based GUI (not optional though for a succesful compilation, see https://github.com/ethereum/cpp-ethereum/issues/452 ) -RUN apt-get install -qy libncurses5-dev - -# Qt-based GUI -# RUN apt-get install -qy qtbase5-dev qt5-default qtdeclarative5-dev libqt5webkit5-dev +RUN apt-get install -qy libncurses5-dev libcurl4-openssl-dev wget +RUN apt-get install -qy libjsoncpp-dev libargtable2-dev libmicrohttpd-dev # Ethereum PPA RUN apt-get install -qy software-properties-common RUN add-apt-repository ppa:ethereum/ethereum +RUN add-apt-repository ppa:ethereum/ethereum-dev RUN apt-get update RUN apt-get install -qy libcryptopp-dev libjson-rpc-cpp-dev +# LLVM-3.5 +RUN wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key|sudo apt-key add - +RUN echo "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.5 main\ndeb-src http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.5 main" > /etc/apt/sources.list.d/llvm-trusty.list +RUN apt-get update +RUN apt-get install -qy llvm-3.5 libedit-dev + +# Fix llvm-3.5 cmake paths +RUN mkdir -p /usr/lib/llvm-3.5/share/llvm && ln -s /usr/share/llvm-3.5/cmake /usr/lib/llvm-3.5/share/llvm/cmake + # Build Ethereum (HEADLESS) RUN git clone --depth=1 https://github.com/ethereum/cpp-ethereum RUN mkdir -p cpp-ethereum/build -RUN cd cpp-ethereum/build && cmake .. -DCMAKE_BUILD_TYPE=Release -DHEADLESS=1 && make -j $(cat /proc/cpuinfo | grep processor | wc -l) && make install +RUN cd cpp-ethereum/build && cmake .. -DHEADLESS=1 -DLLVM_DIR=/usr/share/llvm-3.5/cmake -DEVMJIT=1 && make -j $(cat /proc/cpuinfo | grep processor | wc -l) && make install RUN ldconfig ENTRYPOINT ["/usr/local/bin/eth"] From 63ae0faeb18e5f7bd60b5abe6610d5a0f1c57f80 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 2 Mar 2015 20:29:35 +0100 Subject: [PATCH 05/54] Accounts Managemement --- mix/ClientModel.cpp | 39 +++++++++++++---------------- mix/ClientModel.h | 4 ++- mix/MixClient.cpp | 26 +++++++++++++++---- mix/MixClient.h | 6 ++--- mix/qml/DeploymentDialog.qml | 2 +- mix/qml/Ether.qml | 4 +-- mix/qml/StateDialog.qml | 48 +++++++++++++++++++++++++----------- mix/qml/StateListModel.qml | 32 ++++++++++++++++++------ mix/qml/StatusPane.qml | 2 -- 9 files changed, 106 insertions(+), 57 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 11a34c211..ef6963f32 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -47,8 +47,6 @@ namespace dev namespace mix { -//const Secret c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); - class RpcConnector: public jsonrpc::AbstractServerConnector { public: @@ -89,7 +87,7 @@ ClientModel::ClientModel(AppContext* _context): connect(this, &ClientModel::runComplete, this, &ClientModel::showDebugger, Qt::QueuedConnection); m_client.reset(new MixClient(QStandardPaths::writableLocation(QStandardPaths::TempLocation).toStdString())); - m_web3Server.reset(new Web3Server(*m_rpcConnector.get(), std::vector { m_client->userAccount() }, m_client.get())); + m_web3Server.reset(new Web3Server(*m_rpcConnector.get(), m_client->userAccounts(), m_client.get())); connect(m_web3Server.get(), &Web3Server::newTransaction, this, &ClientModel::onNewTransaction, Qt::DirectConnection); _context->appEngine()->rootContext()->setContextProperty("clientModel", this); } @@ -138,13 +136,10 @@ void ClientModel::mine() }); } -QString ClientModel::newAddress() const +QString ClientModel::newAddress() { - KeyPair a = KeyPair.create(); - return toHex(a.secret().ref()); - //m_client.addBalance(a.address(), _balance, 0); - //emit accountCreated; - //return QString::fromStdString(toHex(a.address().ref())); + KeyPair a = KeyPair::create(); + return QString::fromStdString(toHex(a.secret().ref())); } QVariantMap ClientModel::contractAddresses() const @@ -157,7 +152,7 @@ QVariantMap ClientModel::contractAddresses() const void ClientModel::debugDeployment() { - executeSequence(std::vector(), 10000000 * ether); + executeSequence(std::vector(), std::map()); } void ClientModel::setupState(QVariantMap _state) @@ -165,6 +160,13 @@ void ClientModel::setupState(QVariantMap _state) QVariantList balances = _state.value("balances").toList(); QVariantList transactions = _state.value("transactions").toList(); + std::map accounts; + for (auto const& b: balances) + { + QVariantMap address = b.toMap(); + accounts.insert(std::make_pair(Secret(address.value("secret").toString().toStdString()), (qvariant_cast(address.value("balance")))->toU256Wei())); + } + std::vector transactionSequence; for (auto const& t: transactions) { @@ -205,10 +207,10 @@ void ClientModel::setupState(QVariantMap _state) transactionSequence.push_back(transactionSettings); } } - executeSequence(transactionSequence, balances); + executeSequence(transactionSequence, accounts); } -void ClientModel::executeSequence(std::vector const& _sequence, QVariantList _balances) +void ClientModel::executeSequence(std::vector const& _sequence, std::map _balances) { if (m_running) BOOST_THROW_EXCEPTION(ExecutionStateException()); @@ -222,14 +224,7 @@ void ClientModel::executeSequence(std::vector const& _seque { try { - std::map balancesMap; - for (auto b: _balances) - { - QVariantMap address = b.toMap(); - balancesMap.insert(std::make_pair(KeyPair(Secret(address.value("Secret").toString())).address(), Account(address.value("Balance").toString(), Account::NormalCreation))); - } - - m_client->resetState(balancesMap); + m_client->resetState(_balances); onStateReset(); for (TransactionSettings const& transaction: _sequence) { @@ -363,13 +358,13 @@ void ClientModel::showDebugError(QString const& _error) Address ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction) { - Address newAddress = m_client->transact(m_client->userAccount().secret(), _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice); + Address newAddress = m_client->transact(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice); return newAddress; } void ClientModel::callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr) { - m_client->transact(m_client->userAccount().secret(), _tr.value, _contract, _data, _tr.gas, _tr.gasPrice); + m_client->transact(_tr.sender, _tr.value, _contract, _data, _tr.gas, _tr.gasPrice); } RecordLogEntry* ClientModel::lastBlock() const diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 8cb79cca2..f6863314c 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -66,6 +66,8 @@ struct TransactionSettings QList parameterValues; /// Standard contract url QString stdContractUrl; + /// Sender + Secret sender; }; @@ -193,7 +195,7 @@ signals: private: RecordLogEntry* lastBlock() const; QVariantMap contractAddresses() const; - void executeSequence(std::vector const& _sequence, u256 _balance); + void executeSequence(std::vector const& _sequence, std::map _balances); dev::Address deployContract(bytes const& _code, TransactionSettings const& _tr = TransactionSettings()); void callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr); void onNewTransaction(); diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index d1ef36e41..d7559e9b8 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -40,6 +40,7 @@ namespace dev namespace mix { +const Secret c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); const u256 c_mixGenesisDifficulty = (u256) 1 << 4; class MixBlockChain: public dev::eth::BlockChain @@ -61,16 +62,16 @@ public: }; MixClient::MixClient(std::string const& _dbPath): - m_userAccount(c_userAccountSecret), m_dbPath(_dbPath), m_minigThreads(0) + m_dbPath(_dbPath), m_minigThreads(0) { - resetState(10000000 * ether); + //resetState(); } MixClient::~MixClient() { } -void MixClient::resetState(std::map _genesisState) +void MixClient::resetState(std::map _accounts) { WriteGuard l(x_state); Guard fl(m_filterLock); @@ -80,11 +81,26 @@ void MixClient::resetState(std::map _genesisState) m_stateDB = OverlayDB(); TrieDB accountState(&m_stateDB); accountState.init(); - dev::eth::commit(_genesisState, static_cast(m_stateDB), accountState); + + std::map genesisState; + if (_accounts.size() > 0) + for (auto account: _accounts) + { + KeyPair a = KeyPair(account.first); + m_userAccounts.push_back(a); + genesisState.insert(std::make_pair(a.address(), Account(account.second, Account::NormalCreation))); + } + else + { + KeyPair a = KeyPair(c_defaultUserAccountSecret); + m_userAccounts.push_back(a); + genesisState.insert(std::make_pair(a.address() , Account(u256(10000 * ether), Account::NormalCreation))); + } + dev::eth::commit(genesisState, static_cast(m_stateDB), accountState); h256 stateRoot = accountState.root(); m_bc.reset(); m_bc.reset(new MixBlockChain(m_dbPath, stateRoot)); - m_state = eth::State(m_userAccount.address(), m_stateDB, BaseState::Empty); + m_state = eth::State(genesisState.begin()->first , m_stateDB, BaseState::Empty); m_state.sync(bc()); m_startState = m_state; m_executions.clear(); diff --git a/mix/MixClient.h b/mix/MixClient.h index cd231cd43..55a40eb2a 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -42,8 +42,7 @@ public: MixClient(std::string const& _dbPath); virtual ~MixClient(); /// Reset state to the empty state with given balance. - void resetState(u256 _balance); - KeyPair const& userAccount() const { return m_userAccount; } + void resetState(std::map _accounts); void mine(); ExecutionResult const& lastExecution() const; ExecutionResults const& executions() const; @@ -91,6 +90,7 @@ public: bool submitNonce(h256 const&) override { return false; } /// @returns the last mined block information eth::BlockInfo blockInfo() const; + std::vector userAccounts() { return m_userAccounts; } private: void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state, bool _call); @@ -99,7 +99,7 @@ private: MixBlockChain& bc() { return *m_bc; } MixBlockChain const& bc() const { return *m_bc; } - KeyPair m_userAccount; + std::vector m_userAccounts; eth::State m_state; eth::State m_startState; OverlayDB m_stateDB; diff --git a/mix/qml/DeploymentDialog.qml b/mix/qml/DeploymentDialog.qml index 703246998..5e55e9800 100644 --- a/mix/qml/DeploymentDialog.qml +++ b/mix/qml/DeploymentDialog.qml @@ -267,7 +267,7 @@ Window { MessageDialog { id: errorDialog standardButtons: StandardButton.Ok - icon: StandardIcon.Error + icon: StandardIcon.Critical } RowLayout diff --git a/mix/qml/Ether.qml b/mix/qml/Ether.qml index 1a0f7ffe6..dd9022b81 100644 --- a/mix/qml/Ether.qml +++ b/mix/qml/Ether.qml @@ -20,7 +20,7 @@ RowLayout { function update() { - if (value !== undefined) + if (value) { etherValueEdit.text = value.value; selectUnit(value.unit); @@ -54,7 +54,7 @@ RowLayout { id: units onCurrentTextChanged: { - if (value !== undefined) + if (value) { value.setUnit(currentText); formattedValue.text = value.format(); diff --git a/mix/qml/StateDialog.qml b/mix/qml/StateDialog.qml index b63a7e178..5f9100e9a 100644 --- a/mix/qml/StateDialog.qml +++ b/mix/qml/StateDialog.qml @@ -29,8 +29,8 @@ Window { function open(index, item, setDefault) { stateIndex = index; stateTitle = item.title; - //balanceField.value = item.balance; transactionsModel.clear(); + stateTransactions = []; var transactions = item.transactions; for (var t = 0; t < transactions.length; t++) { @@ -38,8 +38,9 @@ Window { stateTransactions.push(item.transactions[t]); } + accountsModel.clear(); stateAccounts = []; - for (var k = 0; k < item.accounts; k++) + for (var k = 0; k < item.accounts.length; k++) { accountsModel.append(item.accounts[k]); stateAccounts.push(item.accounts[k]); @@ -62,7 +63,6 @@ Window { function getItem() { var item = { title: stateDialog.stateTitle, - //balance: stateDialog.stateBalance, transactions: [], accounts: [] } @@ -105,24 +105,38 @@ Window { text: qsTr("Accounts") } - Rectangle + Button { - Button { - text: "add new accounts" - onClicked: accountsModel.newAccount("10000", QEther.Ether); - } + iconSource: "qrc:/qml/img/plus.png" + action: newAccountAction + width: 10 + height: 10 + } + + Action { + id: newAccountAction + tooltip: qsTr("Add new Account") + onTriggered: accountsModel.newAccount("10000", QEther.Ether); } TableView { + Layout.fillWidth: true model: accountsModel TableViewColumn { role: "secret" - title: qsTr("Address") + title: qsTr("Secret") width: 100 delegate: Item { - DefaultLabel { - text: styleData.value + Rectangle + { + height: 25 + DefaultLabel { + anchors.verticalCenter: parent.verticalCenter + text: { + return styleData.value.substring(0, 5) + '...'; + } + } } } } @@ -135,11 +149,16 @@ Window { Ether { id: balanceField edit: true - displayFormattedValue: true + displayFormattedValue: false value: styleData.value } } } + rowDelegate: + Rectangle { + color: "transparent" + height: 40; + } } } @@ -242,8 +261,9 @@ Window { function newAccount(_balance, _unit) { - accountsModel.append({ secret: _secret, balance: QEtherHelper.createEther(_balance, _unit) }); - stateAccounts.push({ secret: _secret, balance: QEtherHelper.createEther(_balance, _unit) }); + var secret = clientModel.newAddress(); + accountsModel.append({ secret: secret, balance: QEtherHelper.createEther(_balance, _unit) }); + stateAccounts.push({ secret: secret, balance: QEtherHelper.createEther(_balance, _unit) }); } function removeAccount(_i) diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index 640ddfe96..e8f4a6b5e 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -15,8 +15,16 @@ Item { function fromPlainStateItem(s) { return { title: s.title, - balance: QEtherHelper.createEther(s.balance.value, s.balance.unit), - transactions: s.transactions.map(fromPlainTransactionItem) + transactions: s.transactions.map(fromPlainTransactionItem), + accounts: s.accounts.map(fromPlainAccountItem) + }; + } + + function fromPlainAccountItem(t) + { + return { + secret: t.secret, + balance: QEtherHelper.createEther(t.balance.value, t.balance.unit) }; } @@ -26,7 +34,7 @@ Item { functionId: t.functionId, url: t.url, value: QEtherHelper.createEther(t.value.value, t.value.unit), - gas: QEtherHelper.createBigInt(t.gas.value), //t.gas,//QEtherHelper.createEther(t.gas.value, t.gas.unit), + gas: QEtherHelper.createBigInt(t.gas.value), gasPrice: QEtherHelper.createEther(t.gasPrice.value, t.gasPrice.unit), stdContract: t.stdContract, parameters: {} @@ -65,8 +73,8 @@ Item { function toPlainStateItem(s) { return { title: s.title, - balance: { value: s.balance.value, unit: s.balance.unit }, - transactions: s.transactions.map(toPlainTransactionItem) + transactions: s.transactions.map(toPlainTransactionItem), + accounts: s.accounts.map(toPlainAccountItem) }; } @@ -80,6 +88,17 @@ Item { return ''; } + function toPlainAccountItem(t) + { + return { + secret: t.secret, + balance: { + value: t.balance.value, + unit: t.balance.unit + } + }; + } + function toPlainTransactionItem(t) { var r = { contractId: t.contractId, @@ -152,7 +171,7 @@ Item { ListModel { id: stateListModel - property string defaultSecret: "cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074" + property string defaultSecret: "cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169075" property int defaultStateIndex: 0 signal defaultStateChanged; signal stateListModelReady; @@ -198,7 +217,6 @@ Item { ctorTr.contractId = c; item.transactions.push(ctorTr); } - return item; } diff --git a/mix/qml/StatusPane.qml b/mix/qml/StatusPane.qml index 414a051ec..15db4d688 100644 --- a/mix/qml/StatusPane.qml +++ b/mix/qml/StatusPane.qml @@ -164,8 +164,6 @@ Rectangle { RowLayout { anchors.fill: parent - anchors.top: statusHeader.top - anchors.right: statusHeader.right Rectangle { color: "transparent" From e96942c3c79071f62320f0cf6911e525e417dedb Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 2 Mar 2015 18:10:32 +0100 Subject: [PATCH 06/54] Solidity STOPs in case of failed call. --- libsolidity/ExpressionCompiler.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 430e46b06..63aa8a3c2 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -984,9 +984,10 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio m_context << eth::dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos)); else // send all gas except for the 21 needed to execute "SUB" and "CALL" - m_context << u256(21) << eth::Instruction::GAS << eth::Instruction::SUB; - m_context << eth::Instruction::CALL - << eth::Instruction::POP; // @todo do not ignore failure indicator + m_context << u256(_functionType.valueSet() ? 6741 : 41) << eth::Instruction::GAS << eth::Instruction::SUB; + 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()) @@ -999,10 +1000,12 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio CompilerUtils(m_context).loadFromMemory(0, *firstType, false, true); } -void ExpressionCompiler::appendArgumentsCopyToMemory(vector> const& _arguments, - TypePointers const& _types, - bool _padToWordBoundaries, - bool _padExceptionIfFourBytes) +void ExpressionCompiler::appendArgumentsCopyToMemory( + vector> const& _arguments, + TypePointers const& _types, + bool _padToWordBoundaries, + bool _padExceptionIfFourBytes +) { solAssert(_types.empty() || _types.size() == _arguments.size(), ""); for (size_t i = 0; i < _arguments.size(); ++i) From b883eea32734b8b4a9425694f7e8c6c2b2a5db15 Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 3 Mar 2015 11:36:54 +0100 Subject: [PATCH 07/54] Fix test after change in call failure semantics. --- test/SolidityEndToEndTest.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 87a8eb79f..9587a3488 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -1619,9 +1619,11 @@ BOOST_AUTO_TEST_CASE(gas_and_value_basic) function sendAmount(uint amount) returns (uint256 bal) { return h.getBalance.value(amount)(); } - function outOfGas() returns (bool flagBefore, bool flagAfter, uint myBal) { - flagBefore = h.getFlag(); - h.setFlag.gas(2)(); // should fail due to OOG, return value can be garbage + function outOfGas() returns (bool ret) { + h.setFlag.gas(2)(); // should fail due to OOG + return true; + } + function checkState() returns (bool flagAfter, uint myBal) { flagAfter = h.getFlag(); myBal = this.balance; } @@ -1630,7 +1632,8 @@ BOOST_AUTO_TEST_CASE(gas_and_value_basic) compileAndRun(sourceCode, 20); BOOST_REQUIRE(callContractFunction("sendAmount(uint256)", 5) == encodeArgs(5)); // call to helper should not succeed but amount should be transferred anyway - BOOST_REQUIRE(callContractFunction("outOfGas()", 5) == encodeArgs(false, false, 20 - 5)); + BOOST_REQUIRE(callContractFunction("outOfGas()", 5) == bytes()); + BOOST_REQUIRE(callContractFunction("checkState()", 5) == encodeArgs(false, 20 - 5)); } BOOST_AUTO_TEST_CASE(value_complex) From e4c2c654bc148babf6e284ac9502ec3fb5810991 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 3 Mar 2015 12:46:09 +0100 Subject: [PATCH 08/54] pass Secret to the executing transaction. --- mix/ClientModel.cpp | 10 ++++-- mix/ClientModel.h | 4 +-- mix/MixClient.cpp | 16 +++------ mix/qml/StateDialog.qml | 66 +++++++++++++++++++---------------- mix/qml/StateListModel.qml | 18 ++++++---- mix/qml/TransactionDialog.qml | 33 ++++++++++++++++++ 6 files changed, 96 insertions(+), 51 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index ef6963f32..fedb549c8 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -38,6 +38,7 @@ #include "QEther.h" #include "Web3Server.h" #include "ClientModel.h" +#include "MixClient.h" using namespace dev; using namespace dev::eth; @@ -47,6 +48,8 @@ namespace dev namespace mix { +const Secret c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); + class RpcConnector: public jsonrpc::AbstractServerConnector { public: @@ -157,10 +160,11 @@ void ClientModel::debugDeployment() void ClientModel::setupState(QVariantMap _state) { - QVariantList balances = _state.value("balances").toList(); + QVariantList balances = _state.value("accounts").toList(); QVariantList transactions = _state.value("transactions").toList(); std::map accounts; + accounts.insert(std::make_pair(c_defaultUserAccountSecret, 10000 * ether)); //Default account, used to deploy config contracts. for (auto const& b: balances) { QVariantMap address = b.toMap(); @@ -186,6 +190,7 @@ void ClientModel::setupState(QVariantMap _state) transactionSettings.gasPrice = 10000000000000; transactionSettings.gas = 125000; transactionSettings.value = 0; + transactionSettings.sender = c_defaultUserAccountSecret; transactionSequence.push_back(transactionSettings); } else @@ -193,7 +198,8 @@ void ClientModel::setupState(QVariantMap _state) if (contractId.isEmpty() && m_context->codeModel()->hasContract()) //TODO: This is to support old project files, remove later contractId = m_context->codeModel()->contracts().keys()[0]; QVariantList qParams = transaction.value("qType").toList(); - TransactionSettings transactionSettings(contractId, functionId, value, gas, gasPrice); + QString sender = transaction.value("sender").toString(); + TransactionSettings transactionSettings(contractId, functionId, value, gas, gasPrice, Secret(sender.toStdString())); for (QVariant const& variant: qParams) { diff --git a/mix/ClientModel.h b/mix/ClientModel.h index f6863314c..2a3e041c1 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -47,8 +47,8 @@ class QVariableDefinition; struct TransactionSettings { TransactionSettings() {} - TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, u256 _gasPrice): - contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasPrice(_gasPrice) {} + TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, u256 _gasPrice, Secret _sender): + contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasPrice(_gasPrice), sender(_sender) {} TransactionSettings(QString const& _stdContractName, QString const& _stdContractUrl): contractId(_stdContractName), stdContractUrl(_stdContractUrl) {} diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index d7559e9b8..c0b165189 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -21,6 +21,7 @@ */ #include +#include #include #include #include @@ -40,7 +41,6 @@ namespace dev namespace mix { -const Secret c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); const u256 c_mixGenesisDifficulty = (u256) 1 << 4; class MixBlockChain: public dev::eth::BlockChain @@ -83,19 +83,13 @@ void MixClient::resetState(std::map _accounts) accountState.init(); std::map genesisState; - if (_accounts.size() > 0) - for (auto account: _accounts) - { - KeyPair a = KeyPair(account.first); - m_userAccounts.push_back(a); - genesisState.insert(std::make_pair(a.address(), Account(account.second, Account::NormalCreation))); - } - else + for (auto account: _accounts) { - KeyPair a = KeyPair(c_defaultUserAccountSecret); + KeyPair a = KeyPair(account.first); m_userAccounts.push_back(a); - genesisState.insert(std::make_pair(a.address() , Account(u256(10000 * ether), Account::NormalCreation))); + genesisState.insert(std::make_pair(a.address(), Account(account.second, Account::NormalCreation))); } + dev::eth::commit(genesisState, static_cast(m_stateDB), accountState); h256 stateRoot = accountState.root(); m_bc.reset(); diff --git a/mix/qml/StateDialog.qml b/mix/qml/StateDialog.qml index 5f9100e9a..38a59a8a7 100644 --- a/mix/qml/StateDialog.qml +++ b/mix/qml/StateDialog.qml @@ -12,7 +12,7 @@ Window { id: modalStateDialog modality: Qt.ApplicationModal - width: 520 + width: 555 height: 480 title: qsTr("Edit State") visible: false @@ -41,8 +41,7 @@ Window { accountsModel.clear(); stateAccounts = []; for (var k = 0; k < item.accounts.length; k++) - { - accountsModel.append(item.accounts[k]); + { accountsModel.append(item.accounts[k]); stateAccounts.push(item.accounts[k]); } @@ -100,23 +99,35 @@ Window { RowLayout { Layout.fillWidth: true - DefaultLabel { - Layout.preferredWidth: 75 - text: qsTr("Accounts") - } - Button + Rectangle { - iconSource: "qrc:/qml/img/plus.png" - action: newAccountAction - width: 10 - height: 10 - } + Layout.preferredWidth: 75 + DefaultLabel { + id: accountsLabel + Layout.preferredWidth: 75 + text: qsTr("Accounts") + } - Action { - id: newAccountAction - tooltip: qsTr("Add new Account") - onTriggered: accountsModel.newAccount("10000", QEther.Ether); + Button + { + anchors.top: accountsLabel.bottom + anchors.topMargin: 10 + iconSource: "qrc:/qml/img/plus.png" + action: newAccountAction + } + + Action { + id: newAccountAction + tooltip: qsTr("Add new Account") + onTriggered: + { + var account = stateListModel.newAccount("1000000", QEther.Ether); + stateAccounts.push(account); + accountsModel.append(account); + + } + } } TableView @@ -124,9 +135,9 @@ Window { Layout.fillWidth: true model: accountsModel TableViewColumn { - role: "secret" - title: qsTr("Secret") - width: 100 + role: "name" + title: qsTr("Name") + width: 120 delegate: Item { Rectangle { @@ -134,7 +145,7 @@ Window { DefaultLabel { anchors.verticalCenter: parent.verticalCenter text: { - return styleData.value.substring(0, 5) + '...'; + return styleData.value } } } @@ -156,8 +167,8 @@ Window { } rowDelegate: Rectangle { - color: "transparent" - height: 40; + color: styleData.alternate ? "transparent" : "#f0f0f0" + height: 30; } } } @@ -259,13 +270,6 @@ Window { ListModel { id: accountsModel - function newAccount(_balance, _unit) - { - var secret = clientModel.newAddress(); - accountsModel.append({ secret: secret, balance: QEtherHelper.createEther(_balance, _unit) }); - stateAccounts.push({ secret: secret, balance: QEtherHelper.createEther(_balance, _unit) }); - } - function removeAccount(_i) { accountsModel.remove(_i); @@ -277,6 +281,7 @@ Window { id: transactionsModel function editTransaction(index) { + transactionDialog.stateAccounts = stateAccounts; transactionDialog.open(index, transactionsModel.get(index)); } @@ -286,6 +291,7 @@ Window { // https://bugreports.qt-project.org/browse/QTBUG-41327 // Second call to signal handler would just edit the item that was just created, no harm done var item = TransactionHelper.defaultTransaction(); + transactionDialog.stateAccounts = stateAccounts; transactionDialog.open(transactionsModel.count, item); } diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index e8f4a6b5e..b53871211 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -23,6 +23,7 @@ Item { function fromPlainAccountItem(t) { return { + name: t.name, secret: t.secret, balance: QEtherHelper.createEther(t.balance.value, t.balance.unit) }; @@ -91,6 +92,7 @@ Item { function toPlainAccountItem(t) { return { + name: t.name, secret: t.secret, balance: { value: t.balance.value, @@ -171,7 +173,6 @@ Item { ListModel { id: stateListModel - property string defaultSecret: "cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169075" property int defaultStateIndex: 0 signal defaultStateChanged; signal stateListModelReady; @@ -186,18 +187,23 @@ Item { }; } + function newAccount(_balance, _unit) + { + var secret = clientModel.newAddress(); + var name = qsTr("Account") + " - " + secret.substring(0, 5); + return { name: name, secret: secret, balance: QEtherHelper.createEther(_balance, _unit) }; + } + function createDefaultState() { - var ether = QEtherHelper.createEther("1000000", QEther.Ether); var item = { title: "", transactions: [], accounts: [] }; - item.accounts.push({ - secret: defaultSecret, - balance: ether - }); + item.accounts.push(newAccount("1000000", QEther.Ether)); + + console.log(JSON.stringify(item.accounts)); //add all stdc contracts for (var i = 0; i < contractLibrary.model.count; i++) { diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 434f8a850..997f78779 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -25,6 +25,7 @@ Window { property var itemParams; property bool useTransactionDefaultValue: false property var qType; + property alias stateAccounts: senderComboBox.model signal accepted; @@ -44,6 +45,8 @@ Window { rowFunction.visible = true; itemParams = item.parameters !== undefined ? item.parameters : {}; + if (item.sender) + senderComboBox.select(item.sender); contractsModel.clear(); var contractIndex = -1; @@ -190,6 +193,7 @@ Window { item.functionId = transactionDialog.functionId; } + item.sender = senderComboBox.model[senderComboBox.currentIndex].secret; var orderedQType = []; for (var p = 0; p < transactionDialog.transactionParams.count; p++) { var parameter = transactionDialog.transactionParams.get(p); @@ -210,6 +214,35 @@ Window { id: dialogContent anchors.top: parent.top spacing: 10 + RowLayout + { + id: rowSender + Layout.fillWidth: true + height: 150 + DefaultLabel { + Layout.preferredWidth: 75 + text: qsTr("Sender") + } + ComboBox { + + function select(secret) + { + for (var i in model) + if (model[i].secret === secret) + { + currentIndex = i; + break; + } + } + + id: senderComboBox + Layout.preferredWidth: 350 + currentIndex: 0 + textRole: "name" + editable: false + } + } + RowLayout { id: rowContract From 6d4b77249e99efb256a957cbcfa02a09a2a2a9dc Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 3 Mar 2015 11:28:56 +0100 Subject: [PATCH 09/54] Fixed arrays in ABI. --- libsolidity/Compiler.cpp | 67 +++++++++++++++++++---------------- libsolidity/Types.cpp | 13 +++++-- libsolidity/Types.h | 1 + test/SolidityEndToEndTest.cpp | 8 ++--- 4 files changed, 53 insertions(+), 36 deletions(-) diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index 580fd5b62..acc30cf35 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -205,42 +205,49 @@ void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool { // We do not check the calldata size, everything is zero-padded. unsigned offset(CompilerUtils::dataStartOffset); - bool const c_padToWords = true; - unsigned dynamicParameterCount = 0; + bigint parameterHeadEnd = offset; for (TypePointer const& type: _typeParameters) - if (type->isDynamicallySized()) - dynamicParameterCount++; - offset += dynamicParameterCount * 32; - unsigned currentDynamicParameter = 0; + parameterHeadEnd += type->isDynamicallySized() ? 32 : + CompilerUtils::getPaddedSize(type->getCalldataEncodedSize()); + solAssert(parameterHeadEnd <= numeric_limits::max(), "Arguments too large."); + + unsigned stackHeightOfPreviousDynamicArgument = 0; + ArrayType const* previousDynamicType = nullptr; for (TypePointer const& type: _typeParameters) - if (type->isDynamicallySized()) + { + switch (type->getCategory()) { - // value on stack: [calldata_offset] (only if we are already in dynamic mode) - if (currentDynamicParameter == 0) - // switch from static to dynamic + case Type::Category::Array: + if (type->isDynamicallySized()) + { + // put on stack: data_offset length + unsigned newStackHeight = m_context.getStackHeight(); + if (previousDynamicType) + { + // Retrieve data start offset by adding length to start offset of previous dynamic type + unsigned stackDepth = m_context.getStackHeight() - stackHeightOfPreviousDynamicArgument; + m_context << eth::dupInstruction(stackDepth) << eth::dupInstruction(stackDepth); + ArrayUtils(m_context).convertLengthToSize(*previousDynamicType); + m_context << u256(32) << eth::Instruction::MUL << eth::Instruction::ADD; + } + else + m_context << u256(parameterHeadEnd); + stackHeightOfPreviousDynamicArgument = newStackHeight; + previousDynamicType = &dynamic_cast(*type); + offset += CompilerUtils(m_context).loadFromMemory(offset, IntegerType(256), !_fromMemory); + } + else + { m_context << u256(offset); - // retrieve length - CompilerUtils(m_context).loadFromMemory( - CompilerUtils::dataStartOffset + currentDynamicParameter * 32, - IntegerType(256), !_fromMemory, c_padToWords); - // stack: offset length - // add 32-byte padding to copy of length - m_context << u256(32) << eth::Instruction::DUP1 << u256(31) - << eth::Instruction::DUP4 << eth::Instruction::ADD - << eth::Instruction::DIV << eth::Instruction::MUL; - // stack: offset length padded_length - m_context << eth::Instruction::DUP3 << eth::Instruction::ADD; - currentDynamicParameter++; - // stack: offset length next_calldata_offset + offset += CompilerUtils::getPaddedSize(type->getCalldataEncodedSize()); + } + break; + default: + solAssert(!type->isDynamicallySized(), "Unknown dynamically sized type: " + type->toString()); + offset += CompilerUtils(m_context).loadFromMemory(offset, *type, !_fromMemory, true); } - else if (currentDynamicParameter == 0) - // we can still use static load - offset += CompilerUtils(m_context).loadFromMemory(offset, *type, !_fromMemory, c_padToWords); - else - CompilerUtils(m_context).loadFromMemoryDynamic(*type, !_fromMemory, c_padToWords); - if (dynamicParameterCount > 0) - m_context << eth::Instruction::POP; + } } void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters) diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 22d612cd9..96feefff5 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -570,6 +570,15 @@ bool ArrayType::operator==(Type const& _other) const return isDynamicallySized() || getLength() == other.getLength(); } +unsigned ArrayType::getCalldataEncodedSize() const +{ + if (isDynamicallySized()) + return 0; + bigint size = bigint(getLength()) * (isByteArray() ? 1 : getBaseType()->getCalldataEncodedSize()); + solAssert(size <= numeric_limits::max(), "Array size does not fit unsigned."); + return unsigned(size); +} + u256 ArrayType::getStorageSize() const { if (isDynamicallySized()) @@ -586,8 +595,8 @@ u256 ArrayType::getStorageSize() const unsigned ArrayType::getSizeOnStack() const { if (m_location == Location::CallData) - // offset, length (stack top) - return 2; + // offset [length] (stack top) + return 1 + (isDynamicallySized() ? 1 : 0); else // offset return 1; diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 9961f03a3..8474c6c03 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -302,6 +302,7 @@ public: virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; virtual bool operator==(const Type& _other) const override; + virtual unsigned getCalldataEncodedSize() const override; virtual bool isDynamicallySized() const { return m_hasDynamicLength; } virtual u256 getStorageSize() const override; virtual unsigned getSizeOnStack() const override; diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 87a8eb79f..bc0be186f 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -2504,11 +2504,11 @@ BOOST_AUTO_TEST_CASE(struct_containing_bytes_copy_and_delete) compileAndRun(sourceCode); string data = "123456789012345678901234567890123"; BOOST_CHECK(m_state.storage(m_contractAddress).empty()); - BOOST_CHECK(callContractFunction("set(uint256,bytes,uint256)", u256(data.length()), 12, data, 13) == encodeArgs(true)); + BOOST_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, u256(data.length()), 13, data) == encodeArgs(true)); BOOST_CHECK(!m_state.storage(m_contractAddress).empty()); BOOST_CHECK(callContractFunction("copy()") == encodeArgs(true)); BOOST_CHECK(m_state.storage(m_contractAddress).empty()); - BOOST_CHECK(callContractFunction("set(uint256,bytes,uint256)", u256(data.length()), 12, data, 13) == encodeArgs(true)); + BOOST_CHECK(callContractFunction("set(uint256,bytes,uint256)", 12, u256(data.length()), 13, data) == encodeArgs(true)); BOOST_CHECK(!m_state.storage(m_contractAddress).empty()); BOOST_CHECK(callContractFunction("del()") == encodeArgs(true)); BOOST_CHECK(m_state.storage(m_contractAddress).empty()); @@ -2661,8 +2661,8 @@ BOOST_AUTO_TEST_CASE(bytes_in_arguments) bytes calldata1 = encodeArgs(u256(innercalldata1.length()), 12, innercalldata1, 13); string innercalldata2 = asString(FixedHash<4>(dev::sha3("g(uint256)")).asBytes() + encodeArgs(3)); bytes calldata = encodeArgs( - u256(innercalldata1.length()), u256(innercalldata2.length()), - 12, innercalldata1, innercalldata2, 13); + 12, u256(innercalldata1.length()), u256(innercalldata2.length()), 13, + innercalldata1, innercalldata2); BOOST_CHECK(callContractFunction("test(uint256,bytes,bytes,uint256)", calldata) == encodeArgs(12, (8 + 9) * 3, 13, u256(innercalldata1.length()))); } From e44079cd9ea07c4826a7bdc1d4a15065359b99b7 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 3 Mar 2015 13:03:54 +0100 Subject: [PATCH 10/54] support old project --- mix/qml/StateListModel.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index b53871211..64b32af6f 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -13,6 +13,8 @@ Item { property var stateList: [] function fromPlainStateItem(s) { + if (!s.accounts) + s.accounts = [stateListModel.newAccount("1000000", QEther.Ether)]; //support old project return { title: s.title, transactions: s.transactions.map(fromPlainTransactionItem), From ad97732fead213c6a38c672676d5125629545452 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 3 Mar 2015 13:13:34 +0100 Subject: [PATCH 11/54] unuse function deleted. --- mix/ClientModel.cpp | 5 ----- mix/ClientModel.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index fedb549c8..62891cbc0 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -153,11 +153,6 @@ QVariantMap ClientModel::contractAddresses() const return res; } -void ClientModel::debugDeployment() -{ - executeSequence(std::vector(), std::map()); -} - void ClientModel::setupState(QVariantMap _state) { QVariantList balances = _state.value("accounts").toList(); diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 2a3e041c1..9af8f0aff 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -145,8 +145,6 @@ public: Q_INVOKABLE void mine(); public slots: - /// Run the contract constructor and show debugger window. - void debugDeployment(); /// Setup state, run transaction sequence, show debugger for the last transaction /// @param _state JS object with state configuration void setupState(QVariantMap _state); From f1feb3ae65adaf5e88b4ef720456837c4125d02f Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 3 Mar 2015 14:54:53 +0100 Subject: [PATCH 12/54] allows users to change the account name --- mix/qml/StateDialog.qml | 15 ++++++++++----- mix/qml/StateListModel.qml | 4 +--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/mix/qml/StateDialog.qml b/mix/qml/StateDialog.qml index 38a59a8a7..6a41043aa 100644 --- a/mix/qml/StateDialog.qml +++ b/mix/qml/StateDialog.qml @@ -12,14 +12,13 @@ Window { id: modalStateDialog modality: Qt.ApplicationModal - width: 555 + width: 570 height: 480 title: qsTr("Edit State") visible: false color: StateDialogStyle.generic.backgroundColor property alias stateTitle: titleField.text - //property alias stateBalance: balanceField.value property alias isDefault: defaultCheckBox.checked property int stateIndex property var stateTransactions: [] @@ -41,7 +40,8 @@ Window { accountsModel.clear(); stateAccounts = []; for (var k = 0; k < item.accounts.length; k++) - { accountsModel.append(item.accounts[k]); + { + accountsModel.append(item.accounts[k]); stateAccounts.push(item.accounts[k]); } @@ -125,13 +125,13 @@ Window { var account = stateListModel.newAccount("1000000", QEther.Ether); stateAccounts.push(account); accountsModel.append(account); - } } } TableView { + id: accountsView Layout.fillWidth: true model: accountsModel TableViewColumn { @@ -142,8 +142,13 @@ Window { Rectangle { height: 25 - DefaultLabel { + width: parent.width + DefaultTextField { anchors.verticalCenter: parent.verticalCenter + onTextChanged: { + if (styleData.row > -1) + stateAccounts[styleData.row].name = text; + } text: { return styleData.value } diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index 64b32af6f..4b83c54d7 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -192,7 +192,7 @@ Item { function newAccount(_balance, _unit) { var secret = clientModel.newAddress(); - var name = qsTr("Account") + " - " + secret.substring(0, 5); + var name = qsTr("Account") + "-" + secret.substring(0, 4); return { name: name, secret: secret, balance: QEtherHelper.createEther(_balance, _unit) }; } @@ -205,8 +205,6 @@ Item { item.accounts.push(newAccount("1000000", QEther.Ether)); - console.log(JSON.stringify(item.accounts)); - //add all stdc contracts for (var i = 0; i < contractLibrary.model.count; i++) { var contractTransaction = defaultTransactionItem(); From 5695d0ee253e0d8ff205a014ad95e5c3bda146e4 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 27 Feb 2015 12:48:34 +0100 Subject: [PATCH 13/54] Adding argument for structured logging and propagating it forward - Also style fixes when problems encountered --- eth/main.cpp | 61 +++++++++++--------- libethereum/Client.cpp | 9 +-- libethereum/Client.h | 3 +- libethereum/EthereumHost.cpp | 6 +- libethereum/EthereumHost.h | 3 +- libp2p/Host.cpp | 108 ++++++++++++++++++----------------- libp2p/Host.h | 3 +- libwebthree/WebThree.cpp | 7 ++- libwebthree/WebThree.h | 5 +- 9 files changed, 111 insertions(+), 94 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 5051580a5..c9bef172e 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -97,38 +97,39 @@ void interactiveHelp() void help() { cout - << "Usage eth [OPTIONS] " << endl - << "Options:" << endl - << " -a,--address Set the coinbase (mining payout) address to addr (default: auto)." << endl - << " -b,--bootstrap Connect to the default Ethereum peerserver." << endl - << " -c,--client-name Add a name to your client's version string (default: blank)." << endl - << " -d,--db-path Load database from path (default: ~/.ethereum " << endl - << " /Etherum or Library/Application Support/Ethereum)." << endl - << " -f,--force-mining Mine even when there are no transaction to mine (Default: off)" << endl - << " -h,--help Show this help message and exit." << endl - << " -i,--interactive Enter interactive mode (default: non-interactive)." << endl + << "Usage eth [OPTIONS] " << endl + << "Options:" << endl + << " -a,--address Set the coinbase (mining payout) address to addr (default: auto)." << endl + << " -b,--bootstrap Connect to the default Ethereum peerserver." << endl + << " -c,--client-name Add a name to your client's version string (default: blank)." << endl + << " -d,--db-path Load database from path (default: ~/.ethereum " << endl + << " /Etherum or Library/Application Support/Ethereum)." << endl + << " -f,--force-mining Mine even when there are no transaction to mine (Default: off)" << endl + << " -h,--help Show this help message and exit." << endl + << " -i,--interactive Enter interactive mode (default: non-interactive)." << endl #if ETH_JSONRPC - << " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl - << " --json-rpc-port Specify JSON-RPC server port (implies '-j', default: 8080)." << endl + << " -j,--json-rpc Enable JSON-RPC server (default: off)." << endl + << " --json-rpc-port Specify JSON-RPC server port (implies '-j', default: 8080)." << endl #endif - << " -l,--listen Listen on the given port for incoming connected (default: 30303)." << endl - << " -m,--mining Enable mining, optionally for a specified number of blocks (Default: off)" << endl - << " -n,--upnp Use upnp for NAT (default: on)." << endl - << " -L,--local-networking Use peers whose addresses are local." << endl - << " -o,--mode Start a full node or a peer node (Default: full)." << endl - << " -p,--port Connect to remote port (default: 30303)." << endl - << " -r,--remote Connect to remote host (default: none)." << endl - << " -s,--secret Set the secret key for use with send command (default: auto)." << endl - << " -t,--miners Number of mining threads to start (Default: " << thread::hardware_concurrency() << ")" << endl - << " -u,--public-ip Force public ip to given (default; auto)." << endl - << " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (Default: 8)." << endl - << " -x,--peers Attempt to connect to given number of peers (Default: 5)." << endl - << " -V,--version Show the version and exit." << endl + << " -l,--listen Listen on the given port for incoming connected (default: 30303)." << endl + << " -m,--mining Enable mining, optionally for a specified number of blocks (Default: off)" << endl + << " -n,--upnp Use upnp for NAT (default: on)." << endl + << " -L,--local-networking Use peers whose addresses are local." << endl + << " -o,--mode Start a full node or a peer node (Default: full)." << endl + << " -p,--port Connect to remote port (default: 30303)." << endl + << " -r,--remote Connect to remote host (default: none)." << endl + << " -s,--secret Set the secret key for use with send command (default: auto)." << endl + << " --structured-logging Enables structured logging." << endl + << " -t,--miners Number of mining threads to start (Default: " << thread::hardware_concurrency() << ")" << endl + << " -u,--public-ip Force public ip to given (default; auto)." << endl + << " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (Default: 8)." << endl + << " -x,--peers Attempt to connect to given number of peers (Default: 5)." << endl + << " -V,--version Show the version and exit." << endl #if ETH_EVMJIT - << " --jit Use EVM JIT (default: off)." << endl + << " --jit Use EVM JIT (default: off)." << endl #endif ; - exit(0); + exit(0); } string credits(bool _interactive = false) @@ -207,6 +208,7 @@ int main(int argc, char** argv) bool useLocal = false; bool forceMining = false; bool jit = false; + bool structuredLogging = false; string clientName; // Init defaults @@ -279,6 +281,8 @@ int main(int argc, char** argv) } else if ((arg == "-s" || arg == "--secret") && i + 1 < argc) us = KeyPair(h256(fromHex(argv[++i]))); + else if ((arg == "--structured-logging") && i + 1 < argc) + structuredLogging = true; else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc) dbPath = argv[++i]; else if ((arg == "-m" || arg == "--mining") && i + 1 < argc) @@ -360,7 +364,8 @@ int main(int argc, char** argv) mode == NodeMode::Full ? set{"eth", "shh"} : set(), netPrefs, &nodesState, - miners + miners, + structuredLogging ); web3.setIdealPeerCount(peers); eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr; diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 5ea513f0a..e2216de9e 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -59,7 +59,8 @@ void VersionChecker::setOk() } } -Client::Client(p2p::Host* _extNet, std::string const& _dbPath, bool _forceClean, u256 _networkId, int miners): +Client::Client(p2p::Host* _extNet, std::string const& _dbPath, bool _forceClean, + u256 _networkId, int _miners, bool _structuredLogging): Worker("eth"), m_vc(_dbPath), m_bc(_dbPath, !m_vc.ok() || _forceClean), @@ -67,10 +68,10 @@ Client::Client(p2p::Host* _extNet, std::string const& _dbPath, bool _forceClean, m_preMine(Address(), m_stateDB), m_postMine(Address(), m_stateDB) { - m_host = _extNet->registerCapability(new EthereumHost(m_bc, m_tq, m_bq, _networkId)); + m_host = _extNet->registerCapability(new EthereumHost(m_bc, m_tq, m_bq, _networkId, _structuredLogging)); - if (miners > -1) - setMiningThreads(miners); + if (_miners > -1) + setMiningThreads(_miners); else setMiningThreads(); if (_dbPath.size()) diff --git a/libethereum/Client.h b/libethereum/Client.h index 7cd520ab6..1547a9cb3 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -166,7 +166,8 @@ class Client: public MinerHost, public Interface, Worker public: /// New-style Constructor. - explicit Client(p2p::Host* _host, std::string const& _dbPath = std::string(), bool _forceClean = false, u256 _networkId = 0, int miners = -1); + explicit Client(p2p::Host* _host, std::string const& _dbPath = std::string(), bool _forceClean = false, + u256 _networkId = 0, int _miners = -1, bool _structuredLogging = false); /// Destructor. virtual ~Client(); diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 7dfc51b47..4d605a209 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -38,13 +38,15 @@ using namespace dev; using namespace dev::eth; using namespace p2p; -EthereumHost::EthereumHost(BlockChain const& _ch, TransactionQueue& _tq, BlockQueue& _bq, u256 _networkId): +EthereumHost::EthereumHost(BlockChain const& _ch, TransactionQueue& _tq, BlockQueue& _bq, + u256 _networkId, bool _structuredLogging): HostCapability(), Worker ("ethsync"), m_chain (_ch), m_tq (_tq), m_bq (_bq), - m_networkId (_networkId) + m_networkId (_networkId), + m_structuredLogging (_structuredLogging) { m_latestBlockSent = _ch.currentHash(); } diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index dfa928675..c9f92d1e0 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -59,7 +59,7 @@ class EthereumHost: public p2p::HostCapability, Worker public: /// Start server, but don't listen. - EthereumHost(BlockChain const& _ch, TransactionQueue& _tq, BlockQueue& _bq, u256 _networkId); + EthereumHost(BlockChain const& _ch, TransactionQueue& _tq, BlockQueue& _bq, u256 _networkId, bool _structuredLogging); /// Will block on network process events. virtual ~EthereumHost(); @@ -111,6 +111,7 @@ private: u256 m_networkId; EthereumPeer* m_syncer = nullptr; // TODO: switch to weak_ptr + bool m_structuredLogging; DownloadMan m_man; diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 44a17fcb5..4eea8090f 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -45,7 +45,7 @@ void HostNodeTableHandler::processEvent(NodeId const& _n, NodeTableEventType con m_host.onNodeTableEvent(_n, _e); } -Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bytesConstRef _restoreNetwork): +Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bytesConstRef _restoreNetwork, bool _structuredLogging): Worker("p2p", 0), m_restoreNetwork(_restoreNetwork.toBytes()), m_clientVersion(_clientVersion), @@ -54,12 +54,13 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, byte m_ioService(2), m_tcp4Acceptor(m_ioService), m_alias(networkAlias(_restoreNetwork)), - m_lastPing(chrono::steady_clock::time_point::min()) + m_lastPing(chrono::steady_clock::time_point::min()), + m_structuredLogging(_structuredLogging) { for (auto address: m_ifAddresses) if (address.is_v4()) clog(NetNote) << "IP Address: " << address << " = " << (isPrivateAddress(address) ? "[LOCAL]" : "[PEER]"); - + clog(NetNote) << "Id:" << id(); } @@ -88,11 +89,11 @@ void Host::stop() return; m_run = false; } - + // wait for m_timer to reset (indicating network scheduler has stopped) while (!!m_timer) this_thread::sleep_for(chrono::milliseconds(50)); - + // stop worker thread stopWorking(); } @@ -101,12 +102,12 @@ void Host::doneWorking() { // reset ioservice (allows manually polling network, below) m_ioService.reset(); - + // shutdown acceptor m_tcp4Acceptor.cancel(); if (m_tcp4Acceptor.is_open()) m_tcp4Acceptor.close(); - + // There maybe an incoming connection which started but hasn't finished. // Wait for acceptor to end itself instead of assuming it's complete. // This helps ensure a peer isn't stopped at the same time it's starting @@ -133,17 +134,17 @@ void Host::doneWorking() } if (!n) break; - + // poll so that peers send out disconnect packets m_ioService.poll(); } - + // stop network (again; helpful to call before subsequent reset()) m_ioService.stop(); - + // reset network (allows reusing ioservice in future) m_ioService.reset(); - + // finally, clear out peers (in case they're lingering) RecursiveGuard l(x_sessions); m_sessions.clear(); @@ -165,7 +166,7 @@ void Host::registerPeer(std::shared_ptr _s, CapDescs const& _caps) m_peers[_s->m_peer->id] = _s->m_peer; m_sessions[_s->m_peer->id] = _s; } - + unsigned o = (unsigned)UserPacket; for (auto const& i: _caps) if (haveCapability(i)) @@ -181,7 +182,7 @@ void Host::onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e) if (_e == NodeEntryAdded) { clog(NetNote) << "p2p.host.nodeTable.events.nodeEntryAdded " << _n; - + auto n = m_nodeTable->node(_n); if (n) { @@ -198,12 +199,12 @@ void Host::onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e) p->endpoint = NodeIPEndpoint(n.endpoint.udp, n.endpoint.tcp); p->required = n.required; m_peers[_n] = p; - + clog(NetNote) << "p2p.host.peers.events.peersAdded " << _n << p->endpoint.tcp.address() << p->endpoint.udp.address(); } p->endpoint.tcp = n.endpoint.tcp; } - + // TODO: Implement similar to discover. Attempt connecting to nodes // until ideal peer count is reached; if all nodes are tried, // repeat. Notably, this is an integrated process such that @@ -219,7 +220,7 @@ void Host::onNodeTableEvent(NodeId const& _n, NodeTableEventType const& _e) else if (_e == NodeEntryRemoved) { clog(NetNote) << "p2p.host.nodeTable.events.nodeEntryRemoved " << _n; - + RecursiveGuard l(x_sessions); m_peers.erase(_n); } @@ -241,7 +242,7 @@ void Host::seal(bytes& _b) void Host::determinePublic(string const& _publicAddress, bool _upnp) { m_peerAddresses.clear(); - + // no point continuing if there are no interface addresses or valid listen port if (!m_ifAddresses.size() || m_listenPort < 1) return; @@ -250,7 +251,7 @@ void Host::determinePublic(string const& _publicAddress, bool _upnp) for (auto addr: m_ifAddresses) if ((m_netPrefs.localNetworking || !isPrivateAddress(addr)) && !isLocalHostAddress(addr)) m_peerAddresses.insert(addr); - + // if user supplied address is a public address then we use it // if user supplied address is private, and localnetworking is enabled, we use it bi::address reqPublicAddr(bi::address(_publicAddress.empty() ? bi::address() : bi::address::from_string(_publicAddress))); @@ -264,7 +265,7 @@ void Host::determinePublic(string const& _publicAddress, bool _upnp) m_tcpPublic = reqPublic; return; } - + // if address wasn't provided, then use first public ipv4 address found for (auto addr: m_peerAddresses) if (addr.is_v4() && !isPrivateAddress(addr)) @@ -272,7 +273,7 @@ void Host::determinePublic(string const& _publicAddress, bool _upnp) m_tcpPublic = bi::tcp::endpoint(*m_peerAddresses.begin(), m_listenPort); return; } - + // or find address via upnp if (_upnp) { @@ -296,7 +297,7 @@ void Host::determinePublic(string const& _publicAddress, bool _upnp) m_tcpPublic = bi::tcp::endpoint(addr, m_listenPort); return; } - + // otherwise address is unspecified m_tcpPublic = bi::tcp::endpoint(bi::address(), m_listenPort); } @@ -304,7 +305,7 @@ void Host::determinePublic(string const& _publicAddress, bool _upnp) void Host::runAcceptor() { assert(m_listenPort > 0); - + if (m_run && !m_accepting) { clog(NetConnect) << "Listening on local port " << m_listenPort << " (public: " << m_tcpPublic << ")"; @@ -325,7 +326,7 @@ void Host::runAcceptor() // It's possible for an accepted connection to return an error in which // case the socket may be open and must be closed to prevent asio from // processing socket events after socket is deallocated. - + bi::tcp::socket *s = new bi::tcp::socket(m_ioService); m_tcp4Acceptor.async_accept(*s, [=](boost::system::error_code ec) { @@ -349,7 +350,7 @@ void Host::runAcceptor() clog(NetWarn) << "ERROR: " << _e.what(); } } - + // asio doesn't close socket on error if (!success && s->is_open()) { @@ -360,7 +361,7 @@ void Host::runAcceptor() m_accepting = false; delete s; - + if (ec.value() < 1) runAcceptor(); }); @@ -376,7 +377,7 @@ void Host::doHandshake(bi::tcp::socket* _socket, NodeId _nodeId) shared_ptr p; if (_nodeId) p = m_peers[_nodeId]; - + if (!p) p.reset(new Peer()); p->endpoint.tcp.address(_socket->remote_endpoint().address()); @@ -399,16 +400,16 @@ void Host::addNode(NodeId const& _node, std::string const& _addr, unsigned short this_thread::sleep_for(chrono::milliseconds(50)); if (!m_run) return; - + if (_tcpPeerPort < 30300 || _tcpPeerPort > 30305) cwarn << "Non-standard port being recorded: " << _tcpPeerPort; - + if (_tcpPeerPort >= /*49152*/32768) { cwarn << "Private port being recorded - setting to 0"; _tcpPeerPort = 0; } - + boost::system::error_code ec; bi::address addr = bi::address::from_string(_addr, ec); if (ec) @@ -435,20 +436,20 @@ void Host::connect(std::shared_ptr const& _p) this_thread::sleep_for(chrono::milliseconds(50)); if (!m_run) return; - + if (havePeerSession(_p->id)) { clog(NetWarn) << "Aborted connect. Node already connected."; return; } - + if (!m_nodeTable->haveNode(_p->id)) { clog(NetWarn) << "Aborted connect. Node not in node table."; m_nodeTable->addNode(*_p.get()); return; } - + // prevent concurrently connecting to a node Peer *nptr = _p.get(); { @@ -457,7 +458,7 @@ void Host::connect(std::shared_ptr const& _p) return; m_pendingPeerConns.insert(nptr); } - + clog(NetConnect) << "Attempting connection to node" << _p->id.abridged() << "@" << _p->peerEndpoint() << "from" << id().abridged(); bi::tcp::socket* s = new bi::tcp::socket(m_ioService); s->async_connect(_p->peerEndpoint(), [=](boost::system::error_code const& ec) @@ -474,9 +475,10 @@ void Host::connect(std::shared_ptr const& _p) _p->m_lastDisconnect = NoDisconnect; _p->m_lastConnected = std::chrono::system_clock::now(); _p->m_failedAttempts = 0; + auto ps = make_shared(this, std::move(*s), _p); ps->start(); - + } delete s; Guard l(x_pendingNodeConns); @@ -515,22 +517,22 @@ void Host::run(boost::system::error_code const&) { // reset NodeTable m_nodeTable.reset(); - + // stopping io service allows running manual network operations for shutdown // and also stops blocking worker thread, allowing worker thread to exit m_ioService.stop(); - + // resetting timer signals network that nothing else can be scheduled to run m_timer.reset(); return; } - + m_nodeTable->processEvents(); - + for (auto p: m_sessions) if (auto pp = p.second.lock()) pp->serviceNodesRequest(); - + keepAlivePeers(); disconnectLatePeers(); @@ -544,15 +546,15 @@ void Host::run(boost::system::error_code const&) connect(p.second); break; } - + if (c < m_idealPeerCount) m_nodeTable->discover(); - + auto runcb = [this](boost::system::error_code const& error) { run(error); }; m_timer->expires_from_now(boost::posix_time::milliseconds(c_timerInterval)); m_timer->async_wait(runcb); } - + void Host::startedWorking() { asserts(!m_timer); @@ -566,33 +568,33 @@ void Host::startedWorking() m_timer.reset(new boost::asio::deadline_timer(m_ioService)); m_run = true; } - + // try to open acceptor (todo: ipv6) m_listenPort = Network::tcp4Listen(m_tcp4Acceptor, m_netPrefs.listenPort); - + // start capability threads for (auto const& h: m_capabilities) h.second->onStarting(); - + // determine public IP, but only if we're able to listen for connections // todo: GUI when listen is unavailable in UI if (m_listenPort) { determinePublic(m_netPrefs.publicIP, m_netPrefs.upnp); - + if (m_listenPort > 0) runAcceptor(); } else clog(NetNote) << "p2p.start.notice id:" << id().abridged() << "Listen port is invalid or unavailable. Node Table using default port (30303)."; - + // TODO: add m_tcpPublic endpoint; sort out endpoint stuff for nodetable m_nodeTable.reset(new NodeTable(m_ioService, m_alias, m_listenPort > 0 ? m_listenPort : 30303)); m_nodeTable->setEventHandler(new HostNodeTableHandler(*this)); restoreNetwork(&m_restoreNetwork); - + clog(NetNote) << "p2p.started id:" << id().abridged(); - + run(boost::system::error_code()); } @@ -606,7 +608,7 @@ void Host::keepAlivePeers() { if (chrono::steady_clock::now() - c_keepAliveInterval < m_lastPing) return; - + RecursiveGuard l(x_sessions); for (auto p: m_sessions) if (auto pp = p.second.lock()) @@ -641,7 +643,7 @@ bytes Host::saveNetwork() const peers.push_back(*p.second); } peers.sort(); - + RLPStream network; int count = 0; { @@ -683,7 +685,7 @@ bytes Host::saveNetwork() const count++; } } - + RLPStream ret(3); ret << 1 << m_alias.secret(); ret.appendList(count).appendRaw(network.out(), count); @@ -695,7 +697,7 @@ void Host::restoreNetwork(bytesConstRef _b) // nodes can only be added if network is added if (!isStarted()) BOOST_THROW_EXCEPTION(NetworkStartRequired()); - + RecursiveGuard l(x_sessions); RLP r(_b); if (r.itemCount() > 0 && r[0].isInt() && r[0].toInt() == 1) diff --git a/libp2p/Host.h b/libp2p/Host.h index baf8f0585..93bdce5ef 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -85,7 +85,7 @@ class Host: public Worker public: /// Start server, listening for connections on the given port. - Host(std::string const& _clientVersion, NetworkPreferences const& _n = NetworkPreferences(), bytesConstRef _restoreNetwork = bytesConstRef()); + Host(std::string const& _clientVersion, NetworkPreferences const& _n = NetworkPreferences(), bytesConstRef _restoreNetwork = bytesConstRef(), bool _structuredLogging); /// Will block on network process events. virtual ~Host(); @@ -234,6 +234,7 @@ private: std::chrono::steady_clock::time_point m_lastPing; ///< Time we sent the last ping to all peers. bool m_accepting = false; + bool m_structuredLogging; }; } diff --git a/libwebthree/WebThree.cpp b/libwebthree/WebThree.cpp index bee297a79..f1c2ffe82 100644 --- a/libwebthree/WebThree.cpp +++ b/libwebthree/WebThree.cpp @@ -35,15 +35,16 @@ using namespace dev::p2p; using namespace dev::eth; using namespace dev::shh; -WebThreeDirect::WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean, std::set const& _interfaces, NetworkPreferences const& _n, bytesConstRef _network, int miners): +WebThreeDirect::WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean, + std::set const& _interfaces, NetworkPreferences const& _n, + bytesConstRef _network, int _miners, bool _structuredLogging): m_clientVersion(_clientVersion), m_net(_clientVersion, _n, _network) { if (_dbPath.size()) Defaults::setDBPath(_dbPath); if (_interfaces.count("eth")) - m_ethereum.reset(new eth::Client(&m_net, _dbPath, _forceClean, 0, miners)); - + m_ethereum.reset(new eth::Client(&m_net, _dbPath, _forceClean, 0, _miners, _structuredLogging)); if (_interfaces.count("shh")) m_whisper = m_net.registerCapability(new WhisperHost); diff --git a/libwebthree/WebThree.h b/libwebthree/WebThree.h index 4fa1d1fe5..03adbd727 100644 --- a/libwebthree/WebThree.h +++ b/libwebthree/WebThree.h @@ -103,7 +103,10 @@ class WebThreeDirect : public WebThreeNetworkFace public: /// Constructor for private instance. If there is already another process on the machine using @a _dbPath, then this will throw an exception. /// ethereum() may be safely static_cast()ed to a eth::Client*. - WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean = false, std::set const& _interfaces = {"eth", "shh"}, p2p::NetworkPreferences const& _n = p2p::NetworkPreferences(), bytesConstRef _network = bytesConstRef(), int miners = -1); + WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean = false, + std::set const& _interfaces = {"eth", "shh"}, + p2p::NetworkPreferences const& _n = p2p::NetworkPreferences(), + bytesConstRef _network = bytesConstRef(), int _miners = -1, bool _structuredLogging = false); /// Destructor. ~WebThreeDirect(); From d0c1c510bdeea0b9d582ca809e9cc4925dd8d65a Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 27 Feb 2015 17:52:53 +0100 Subject: [PATCH 14/54] Adding StructuredLogger class and using it in various places - Structured logger is injected as a dependency where needed. - Still a work in progress --- eth/main.cpp | 26 ++--- libdevcore/CMakeLists.txt | 1 + libdevcore/StructuredLogger.cpp | 166 ++++++++++++++++++++++++++++++++ libdevcore/StructuredLogger.h | 59 ++++++++++++ libethereum/BlockChain.cpp | 25 ++++- libethereum/BlockChain.h | 7 +- libethereum/Client.cpp | 14 ++- libethereum/Client.h | 6 +- libethereum/Miner.cpp | 5 +- libethereum/Miner.h | 5 +- libethereum/State.cpp | 12 ++- libethereum/State.h | 4 +- libp2p/Host.cpp | 9 +- libp2p/Host.h | 66 +++++++------ libwebthree/WebThree.cpp | 8 +- libwebthree/WebThree.h | 2 +- 16 files changed, 345 insertions(+), 70 deletions(-) create mode 100644 libdevcore/StructuredLogger.cpp create mode 100644 libdevcore/StructuredLogger.h diff --git a/eth/main.cpp b/eth/main.cpp index c9bef172e..938bf936b 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -354,22 +355,25 @@ int main(int argc, char** argv) cout << credits(); + unique_ptr structuredLogger(new StructuredLogger(structuredLogging)); VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter); NetworkPreferences netPrefs(listenPort, publicIP, upnp, useLocal); auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp"); + std::string clientImplString = "Ethereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) + (jit ? "/JIT" : ""); dev::WebThreeDirect web3( - "Ethereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) + (jit ? "/JIT" : ""), + clientImplString, dbPath, false, mode == NodeMode::Full ? set{"eth", "shh"} : set(), netPrefs, &nodesState, miners, - structuredLogging + structuredLogger.get() ); web3.setIdealPeerCount(peers); eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr; - + if (structuredLogging) + structuredLogger->logStarting(clientImplString, dev::Version); if (c) { c->setForceMining(forceMining); @@ -530,7 +534,7 @@ int main(int argc, char** argv) string sdata; iss >> hexAddr >> amount >> gasPrice >> gas >> sechex >> sdata; - + cnote << "Data:"; cnote << sdata; bytes data = dev::eth::parseData(sdata); @@ -613,7 +617,7 @@ int main(int argc, char** argv) if (size > 0) cwarn << "Invalid address length:" << size; } - else + else { auto const& bc =c->blockChain(); auto h = bc.currentHash(); @@ -635,7 +639,7 @@ int main(int argc, char** argv) cwarn << "transaction rejected"; } } - } + } else cwarn << "Require parameters: send ADDRESS AMOUNT"; } @@ -693,7 +697,7 @@ int main(int argc, char** argv) cwarn << "Minimum gas amount is" << minGas; else c->transact(us.secret(), endowment, init, gas, gasPrice); - } + } else cwarn << "Require parameters: contract ENDOWMENT GASPRICE GAS CODEHEX"; } @@ -811,7 +815,7 @@ int main(int argc, char** argv) string hexSec; iss >> hexSec; us = KeyPair(h256(fromHex(hexSec))); - } + } else cwarn << "Require parameter: setSecret HEXSECRETKEY"; } @@ -852,7 +856,7 @@ int main(int argc, char** argv) RLPStream config(2); config << us.secret() << coinbase; writeFile(path, config.out()); - } + } else cwarn << "Require parameter: exportConfig PATH"; } @@ -868,10 +872,10 @@ int main(int argc, char** argv) RLP config(b); us = KeyPair(config[0].toHash()); coinbase = config[1].toHash
(); - } + } else cwarn << path << "has no content!"; - } + } else cwarn << "Require parameter: importConfig PATH"; } diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index e3851b7ce..d11fa7ea4 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -27,6 +27,7 @@ endif() target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES}) +target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) # transitive dependencies for windows executables if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") diff --git a/libdevcore/StructuredLogger.cpp b/libdevcore/StructuredLogger.cpp new file mode 100644 index 000000000..458f3dc79 --- /dev/null +++ b/libdevcore/StructuredLogger.cpp @@ -0,0 +1,166 @@ +/* + 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 StructuredLogger.h + * @author Lefteris Karapetsas + * @date 2015 + * + * A simple helper class for the structured logging + */ + +#include "StructuredLogger.h" + +#include + +using namespace std; + +namespace dev +{ + +char const* StructuredLogger::timePointToString(chrono::system_clock::time_point const& _ts) const +{ + // not using C++11 std::put_time due to gcc bug + // http://stackoverflow.com/questions/14136833/stdput-time-implementation-status-in-gcc + + // TODO: Format it according to Log event Requirements + time_t time = chrono::system_clock::to_time_t(_ts); + return ctime(&time); +} + +void StructuredLogger::outputJson(Json::Value const* _value, std::string const& _name) const +{ + Json::Value event; + event[_name] = _value; + cout << event; +} + +void StructuredLogger::logStarting(string const& _clientImpl, const char* _ethVersion) +{ + if (m_enabled) + { + Json::Value event; + event["comment"] = "one of the first log events, before any operation is started"; + event["client_implt"] = _clientImpl; + event["eth_version"] = std::string(_ethVersion); + event["ts"] = string(timePointToString(std::chrono::system_clock::now())); + + outputJson(&event, "starting"); + } +} + +void StructuredLogger::logP2PConnected(string const& _id, bi::tcp::endpoint const& _addr, + chrono::system_clock::time_point const& _ts, unsigned int _numConnections) const +{ + if (m_enabled) + { + std::stringstream addrStream; + addrStream << _addr; + Json::Value event; + event["remote_version_string"] = ""; //TODO + event["comment"] = "as soon as a successful connection to another node is established"; + event["remote_addr"] = addrStream.str(); + event["remote_id"] = _id; + event["num_connections"] = Json::Value(_numConnections); + event["ts"] = string(timePointToString(_ts)); + + outputJson(&event, "p2p.connected"); + } +} + +void StructuredLogger::logP2PDisconnected(string const& _id, unsigned int _numConnections, bi::tcp::endpoint const& _addr) const +{ + if (m_enabled) + { + std::stringstream addrStream; + addrStream << _addr; + Json::Value event; + event["comment"] = "as soon as a disconnection from another node happened"; + event["remote_addr"] = addrStream.str(); + event["remote_id"] = _id; + event["num_connections"] = Json::Value(_numConnections); + event["ts"] = string(timePointToString(chrono::system_clock::now())); + + outputJson(&event, "p2p.disconnected"); + } +} + +void StructuredLogger::logMinedNewBlock(string const& _hash, string const& _blockNumber, + string const& _chainHeadHash, string const& _prevHash) const +{ + if (m_enabled) + { + Json::Value event; + event["comment"] = "as soon as the block was mined, before adding as new head"; + event["block_hash"] = _hash; + event["block_number"] = _blockNumber; + event["chain_head_hash"] = _chainHeadHash; + event["ts"] = string(timePointToString(std::chrono::system_clock::now())); + event["block_prev_hash"] = _prevHash; + + outputJson(&event, "eth.miner.new_block"); + } +} + +void StructuredLogger::logChainReceivedNewBlock(string const& _hash, string const& _blockNumber, + string const& _chainHeadHash, string const& _remoteID, string const& _prevHash) const +{ + if (m_enabled) + { + Json::Value event; + event["comment"] = "whenever a _new_ block is received, before adding"; + event["block_hash"] = _hash; + event["block_number"] = _blockNumber; + event["chain_head_hash"] = _chainHeadHash; + event["remote_id"] = _remoteID; + event["ts"] = string(timePointToString(chrono::system_clock::now())); + event["block_prev_hash"] = _prevHash; + + outputJson(&event, "eth.chain.received.new_block"); + } +} + +void StructuredLogger::logChainNewHead(string const& _hash, string const& _blockNumber, + string const& _chainHeadHash, string const& _prevHash) const +{ + if (m_enabled) + { + Json::Value event; + event["comment"] = "whenever head changes"; + event["block_hash"] = _hash; + event["block_number"] = _blockNumber; + event["chain_head_hash"] = _chainHeadHash; + event["ts"] = string(timePointToString(chrono::system_clock::now())); + event["block_prev_hash"] = _prevHash; + + outputJson(&event, "eth.miner.new_block"); + } +} + +void StructuredLogger::logTransactionReceived(string const& _hash, string const& _remoteId) const +{ + if (m_enabled) + { + Json::Value event; + event["tx_hash"] = _hash; + event["remote_id"] = _remoteId; + event["ts"] = string(timePointToString(chrono::system_clock::now())); + + outputJson(&event, "eth.tx.received"); + } +} + + +} diff --git a/libdevcore/StructuredLogger.h b/libdevcore/StructuredLogger.h new file mode 100644 index 000000000..8d807d9d4 --- /dev/null +++ b/libdevcore/StructuredLogger.h @@ -0,0 +1,59 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file StructuredLogger.h + * @author Lefteris Karapetsas + * @date 2015 + * + * A simple helper class for the structured logging + */ + +#pragma once + +#include +#include +#include + +namespace Json { class Value; } + +namespace dev +{ + +class StructuredLogger +{ +public: + StructuredLogger(bool _enabled): m_enabled(_enabled) {} + + void logStarting(std::string const& _clientImpl, const char* _ethVersion); + void logP2PConnected(std::string const& _id, bi::tcp::endpoint const& _addr, + std::chrono::system_clock::time_point const& _ts, unsigned int _numConnections) const; + void logP2PDisconnected(std::string const& _id, unsigned int _numConnections, bi::tcp::endpoint const& _addr) const; + void logMinedNewBlock(std::string const& _hash, std::string const& _blockNumber, + std::string const& _chainHeadHash, std::string const& _prevHash) const; + void logChainReceivedNewBlock(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, + std::string const& _remoteID, std::string const& _prevHash) const; + void logChainNewHead(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, + std::string const& _prevHash) const; + void logTransactionReceived(std::string const& _hash, std::string const& _remoteId) const; +private: + /// @returns a string representation of a timepoint + char const* timePointToString(std::chrono::system_clock::time_point const& _ts) const; + void outputJson(Json::Value const* _value, std::string const& _name) const; + bool m_enabled; + +}; + +} diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index c7c55758b..0ac9445d7 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -152,7 +153,7 @@ inline string toString(h256s const& _bs) return out.str(); } -h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max) +h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max, StructuredLogger const* _logger) { _bq.tick(*this); @@ -164,7 +165,7 @@ h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max { try { - for (auto h: import(block, _stateDB)) + for (auto h: import(block, _stateDB, _logger)) if (!_max--) break; else @@ -187,11 +188,11 @@ h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max return ret; } -h256s BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB) noexcept +h256s BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, StructuredLogger const* _logger) noexcept { try { - return import(_block, _stateDB); + return import(_block, _stateDB, _logger); } catch (...) { @@ -200,7 +201,7 @@ h256s BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB) } } -h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) +h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, StructuredLogger const* _logger) { // VERIFY: populates from the block and checks the block is internally coherent. BlockInfo bi; @@ -317,6 +318,13 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) } #endif + if (_logger) + _logger->logChainReceivedNewBlock( + bi.headerHash(WithoutNonce).abridged(), + bi.nonce.abridged(), + currentHash().abridged(), + "", // TODO: remote id ?? + bi.parentHash.abridged()); // cnote << "Parent " << bi.parentHash << " has " << details(bi.parentHash).children.size() << " children."; h256s ret; @@ -331,6 +339,13 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) } m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&newHash, 32)); clog(BlockChainNote) << " Imported and best" << td << ". Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(ret); + if (_logger) + _logger->logChainNewHead( + bi.headerHash(WithoutNonce).abridged(), + bi.nonce.abridged(), + currentHash().abridged(), + bi.parentHash.abridged() + ); } else { diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index 0c5587d2a..dc0cd76b2 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -40,6 +40,7 @@ namespace ldb = leveldb; namespace dev { +class StructuredLogger; class OverlayDB; namespace eth @@ -79,15 +80,15 @@ public: void process(); /// Sync the chain with any incoming blocks. All blocks should, if processed in order - h256s sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max); + h256s sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max, StructuredLogger const* _logger); /// Attempt to import the given block directly into the CanonBlockChain and sync with the state DB. /// @returns the block hashes of any blocks that came into/went out of the canonical block chain. - h256s attemptImport(bytes const& _block, OverlayDB const& _stateDB) noexcept; + h256s attemptImport(bytes const& _block, OverlayDB const& _stateDB, StructuredLogger const* _logger = nullptr) noexcept; /// Import block into disk-backed DB /// @returns the block hashes of any blocks that came into/went out of the canonical block chain. - h256s import(bytes const& _block, OverlayDB const& _stateDB); + h256s import(bytes const& _block, OverlayDB const& _stateDB, StructuredLogger const* _logger = nullptr); /// Returns true if the given block is known (though not necessarily a part of the canon chain). bool isKnown(h256 _hash) const; diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index e2216de9e..6c9c1c44e 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "Defaults.h" #include "Executive.h" @@ -60,15 +61,16 @@ void VersionChecker::setOk() } Client::Client(p2p::Host* _extNet, std::string const& _dbPath, bool _forceClean, - u256 _networkId, int _miners, bool _structuredLogging): + u256 _networkId, int _miners, StructuredLogger const* _structuredLogger): Worker("eth"), m_vc(_dbPath), m_bc(_dbPath, !m_vc.ok() || _forceClean), m_stateDB(State::openDB(_dbPath, !m_vc.ok() || _forceClean)), m_preMine(Address(), m_stateDB), - m_postMine(Address(), m_stateDB) + m_postMine(Address(), m_stateDB), + m_structuredLogger(_structuredLogger) { - m_host = _extNet->registerCapability(new EthereumHost(m_bc, m_tq, m_bq, _networkId, _structuredLogging)); + m_host = _extNet->registerCapability(new EthereumHost(m_bc, m_tq, m_bq, _networkId, _structuredLogger)); if (_miners > -1) setMiningThreads(_miners); @@ -416,6 +418,8 @@ void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _ } Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); // cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); + if (m_structuredLogger) + m_structuredLogger->logTransactionReceived(t.sha3().abridged(), t.sender().abridged()); cnote << "New transaction " << t; m_tq.attemptImport(t.rlp()); } @@ -521,7 +525,7 @@ void Client::doWork() h256s hs; { WriteGuard l(x_stateDB); - hs = m_bc.attemptImport(m.blockData(), m_stateDB); + hs = m_bc.attemptImport(m.blockData(), m_stateDB, m_structuredLogger); } if (hs.size()) { @@ -556,7 +560,7 @@ void Client::doWork() cwork << "BQ ==> CHAIN ==> STATE"; OverlayDB db = m_stateDB; x_stateDB.unlock(); - h256s newBlocks = m_bc.sync(m_bq, db, 100); // TODO: remove transactions from m_tq nicely rather than relying on out of date nonce later on. + h256s newBlocks = m_bc.sync(m_bq, db, 100, m_structuredLogger); // TODO: remove transactions from m_tq nicely rather than relying on out of date nonce later on. if (newBlocks.size()) { for (auto i: newBlocks) diff --git a/libethereum/Client.h b/libethereum/Client.h index 1547a9cb3..644a6ed6c 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -44,6 +44,9 @@ namespace dev { + +class StructuredLogger; + namespace eth { @@ -167,7 +170,7 @@ class Client: public MinerHost, public Interface, Worker public: /// New-style Constructor. explicit Client(p2p::Host* _host, std::string const& _dbPath = std::string(), bool _forceClean = false, - u256 _networkId = 0, int _miners = -1, bool _structuredLogging = false); + u256 _networkId = 0, int _miners = -1, StructuredLogger const* _structuredLogger = nullptr); /// Destructor. virtual ~Client(); @@ -365,6 +368,7 @@ private: std::map m_filters; std::map m_watches; + StructuredLogger const* m_structuredLogger; mutable std::chrono::system_clock::time_point m_lastGarbageCollection; }; diff --git a/libethereum/Miner.cpp b/libethereum/Miner.cpp index a049fca2f..03cceed74 100644 --- a/libethereum/Miner.cpp +++ b/libethereum/Miner.cpp @@ -36,9 +36,10 @@ LocalMiner::LocalMiner(MinerHost* _host, unsigned _id): { } -void LocalMiner::setup(MinerHost* _host, unsigned _id) +void LocalMiner::setup(MinerHost* _host, unsigned _id, StructuredLogger const* _structuredLogger) { m_host = _host; + m_structuredLogger = _structuredLogger; setName("miner-" + toString(_id)); } @@ -79,7 +80,7 @@ void LocalMiner::doWork() } if (mineInfo.completed) { - m_mineState.completeMine(); + m_mineState.completeMine(m_structuredLogger); m_host->onComplete(); m_miningStatus = Mined; } diff --git a/libethereum/Miner.h b/libethereum/Miner.h index fd449e995..c8f9691f4 100644 --- a/libethereum/Miner.h +++ b/libethereum/Miner.h @@ -32,6 +32,8 @@ namespace dev { + +class StructuredLogger; namespace eth { @@ -104,7 +106,7 @@ public: ~LocalMiner() { stop(); } /// Setup its basics. - void setup(MinerHost* _host, unsigned _id = 0); + void setup(MinerHost* _host, unsigned _id = 0, StructuredLogger const* _structuredLogger = nullptr); /// Start mining. void start() { startWorking(); } @@ -143,6 +145,7 @@ private: mutable std::mutex x_mineInfo; ///< Lock for the mining progress & history. MineProgress m_mineProgress; ///< What's our progress? std::list m_mineHistory; ///< What the history of our mining? + StructuredLogger const* m_structuredLogger; }; } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 76ad1f269..edaa3a6dc 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -801,12 +802,12 @@ bool State::completeMine(h256 const& _nonce) m_currentBlock.nonce = _nonce; cnote << "Completed" << m_currentBlock.headerHash(WithoutNonce).abridged() << m_currentBlock.nonce.abridged() << m_currentBlock.difficulty << ProofOfWork::verify(m_currentBlock.headerHash(WithoutNonce), m_currentBlock.nonce, m_currentBlock.difficulty); - completeMine(); + completeMine(nullptr); return true; } -void State::completeMine() +void State::completeMine(StructuredLogger const* _structuredLogger) { cdebug << "Completing mine!"; // Got it! @@ -820,6 +821,13 @@ void State::completeMine() ret.swapOut(m_currentBytes); m_currentBlock.hash = sha3(RLP(m_currentBytes)[0].data()); cnote << "Mined " << m_currentBlock.hash.abridged() << "(parent: " << m_currentBlock.parentHash.abridged() << ")"; + if (_structuredLogger) + _structuredLogger->logMinedNewBlock( + m_currentBlock.hash.abridged(), + m_currentBlock.nonce.abridged(), + "", //TODO: chain head hash here ?? + m_currentBlock.parentHash.abridged() + ); // Quickly reset the transactions. // TODO: Leave this in a better state than this limbo, or at least record that it's in limbo. diff --git a/libethereum/State.h b/libethereum/State.h index 813141d17..cd1048d60 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -41,6 +41,8 @@ namespace dev { +class StructuredLogger; + namespace test { class ImportTest; } namespace eth @@ -139,7 +141,7 @@ public: * // unlock * @endcode */ - void completeMine(); + void completeMine(StructuredLogger const* _structuredLogger = nullptr); /// Get the complete current block, including valid nonce. /// Only valid after mine() returns true. diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 4eea8090f..97d785dc6 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include "Session.h" @@ -45,7 +46,7 @@ void HostNodeTableHandler::processEvent(NodeId const& _n, NodeTableEventType con m_host.onNodeTableEvent(_n, _e); } -Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bytesConstRef _restoreNetwork, bool _structuredLogging): +Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bytesConstRef _restoreNetwork, StructuredLogger const* _structuredLogger): Worker("p2p", 0), m_restoreNetwork(_restoreNetwork.toBytes()), m_clientVersion(_clientVersion), @@ -55,7 +56,7 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, byte m_tcp4Acceptor(m_ioService), m_alias(networkAlias(_restoreNetwork)), m_lastPing(chrono::steady_clock::time_point::min()), - m_structuredLogging(_structuredLogging) + m_structuredLogger(_structuredLogger) { for (auto address: m_ifAddresses) if (address.is_v4()) @@ -476,6 +477,10 @@ void Host::connect(std::shared_ptr const& _p) _p->m_lastConnected = std::chrono::system_clock::now(); _p->m_failedAttempts = 0; + if (m_structuredLogger) + m_structuredLogger->logP2PConnected(_p->id.abridged(), _p->peerEndpoint(), _p->m_lastConnected, + 0);// TODO: num_connections + auto ps = make_shared(this, std::move(*s), _p); ps->start(); diff --git a/libp2p/Host.h b/libp2p/Host.h index 93bdce5ef..b93a64556 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -45,6 +45,8 @@ namespace bi = ba::ip; namespace dev { +class StructuredLogger; + namespace p2p { @@ -56,7 +58,7 @@ public: HostNodeTableHandler(Host& _host); Host const& host() const { return m_host; } - + private: virtual void processEvent(NodeId const& _n, NodeTableEventType const& _e); @@ -82,23 +84,24 @@ class Host: public Worker friend class HostNodeTableHandler; friend class Session; friend class HostCapabilityFace; - + public: /// Start server, listening for connections on the given port. - Host(std::string const& _clientVersion, NetworkPreferences const& _n = NetworkPreferences(), bytesConstRef _restoreNetwork = bytesConstRef(), bool _structuredLogging); + Host(std::string const& _clientVersion, NetworkPreferences const& _n = NetworkPreferences(), + bytesConstRef _restoreNetwork = bytesConstRef(), StructuredLogger const* _structuredLogger = nullptr); /// Will block on network process events. virtual ~Host(); - + /// Interval at which Host::run will call keepAlivePeers to ping peers. std::chrono::seconds const c_keepAliveInterval = std::chrono::seconds(30); /// Disconnect timeout after failure to respond to keepAlivePeers ping. std::chrono::milliseconds const c_keepAliveTimeOut = std::chrono::milliseconds(1000); - + /// Default host for current version of client. static std::string pocHost(); - + /// Basic peer network protocol version. unsigned protocolVersion() const; @@ -108,23 +111,23 @@ public: bool haveCapability(CapDesc const& _name) const { return m_capabilities.count(_name) != 0; } CapDescs caps() const { CapDescs ret; for (auto const& i: m_capabilities) ret.push_back(i.first); return ret; } template std::shared_ptr cap() const { try { return std::static_pointer_cast(m_capabilities.at(std::make_pair(T::staticName(), T::staticVersion()))); } catch (...) { return nullptr; } } - + bool havePeerSession(NodeId _id) { RecursiveGuard l(x_sessions); return m_sessions.count(_id) ? !!m_sessions[_id].lock() : false; } - + void addNode(NodeId const& _node, std::string const& _addr, unsigned short _tcpPort, unsigned short _udpPort); - + /// Set ideal number of peers. void setIdealPeerCount(unsigned _n) { m_idealPeerCount = _n; } /// Get peer information. PeerSessionInfos peerSessionInfo() const; - + /// Get number of peers connected. size_t peerCount() const; - + /// Get the address we're listening on currently. std::string listenAddress() const { return m_tcpPublic.address().to_string(); } - + /// Get the port we're listening on currently. unsigned short listenPort() const { return m_tcpPublic.port(); } @@ -138,11 +141,11 @@ public: /// Start network. @threadsafe void start(); - + /// Stop network. @threadsafe /// Resets acceptor, socket, and IO service. Called by deallocator. void stop(); - + /// @returns if network is running. bool isStarted() const { return m_run; } @@ -155,25 +158,25 @@ protected: /// Deserialise the data and populate the set of known peers. void restoreNetwork(bytesConstRef _b); - + private: /// Populate m_peerAddresses with available public addresses. void determinePublic(std::string const& _publicAddress, bool _upnp); - + void connect(std::shared_ptr const& _p); - + /// Ping the peers to update the latency information and disconnect peers which have timed out. void keepAlivePeers(); - + /// Disconnect peers which didn't respond to keepAlivePeers ping prior to c_keepAliveTimeOut. void disconnectLatePeers(); - + /// Called only from startedWorking(). void runAcceptor(); - + /// Handler for verifying handshake siganture before creating session. _nodeId is passed for outbound connections. If successful, socket is moved to Session via std::move. void doHandshake(bi::tcp::socket* _socket, NodeId _nodeId = NodeId()); - + void seal(bytes& _b); /// Called by Worker. Not thread-safe; to be called only by worker. @@ -183,7 +186,7 @@ private: /// Run network. Not thread-safe; to be called only by worker. virtual void doWork(); - + /// Shutdown network. Not thread-safe; to be called only by worker. virtual void doneWorking(); @@ -191,14 +194,14 @@ private: static KeyPair networkAlias(bytesConstRef _b); bytes m_restoreNetwork; ///< Set by constructor and used to set Host key and restore network peers & nodes. - + bool m_run = false; ///< Whether network is running. std::mutex x_runTimer; ///< Start/stop mutex. - + std::string m_clientVersion; ///< Our version string. NetworkPreferences m_netPrefs; ///< Network settings. - + /// Interface addresses (private, public) std::vector m_ifAddresses; ///< Interface addresses. @@ -206,10 +209,10 @@ private: ba::io_service m_ioService; ///< IOService for network stuff. bi::tcp::acceptor m_tcp4Acceptor; ///< Listening acceptor. - + std::unique_ptr m_timer; ///< Timer which, when network is running, calls scheduler() every c_timerInterval ms. static const unsigned c_timerInterval = 100; ///< Interval which m_timer is run when network is connected. - + std::set m_pendingPeerConns; /// Used only by connect(Peer&) to limit concurrently connecting to same node. See connect(shared_ptrconst&). Mutex x_pendingNodeConns; @@ -219,23 +222,22 @@ private: /// Shared storage of Peer objects. Peers are created or destroyed on demand by the Host. Active sessions maintain a shared_ptr to a Peer; std::map> m_peers; - + /// The nodes to which we are currently connected. Used by host to service peer requests and keepAlivePeers and for shutdown. (see run()) /// Mutable because we flush zombie entries (null-weakptrs) as regular maintenance from a const method. mutable std::map> m_sessions; mutable RecursiveMutex x_sessions; unsigned m_idealPeerCount = 5; ///< Ideal number of peers to be connected to. - + std::set m_peerAddresses; ///< Public addresses that peers (can) know us by. std::map> m_capabilities; ///< Each of the capabilities we support. std::chrono::steady_clock::time_point m_lastPing; ///< Time we sent the last ping to all peers. - + StructuredLogger const* m_structuredLogger; bool m_accepting = false; - bool m_structuredLogging; }; - + } } diff --git a/libwebthree/WebThree.cpp b/libwebthree/WebThree.cpp index f1c2ffe82..1025aad55 100644 --- a/libwebthree/WebThree.cpp +++ b/libwebthree/WebThree.cpp @@ -37,14 +37,14 @@ using namespace dev::shh; WebThreeDirect::WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean, std::set const& _interfaces, NetworkPreferences const& _n, - bytesConstRef _network, int _miners, bool _structuredLogging): - m_clientVersion(_clientVersion), - m_net(_clientVersion, _n, _network) + bytesConstRef _network, int _miners, StructuredLogger const* _structuredLogger): + m_clientVersion(_clientVersion), + m_net(_clientVersion, _n, _network, _structuredLogger) { if (_dbPath.size()) Defaults::setDBPath(_dbPath); if (_interfaces.count("eth")) - m_ethereum.reset(new eth::Client(&m_net, _dbPath, _forceClean, 0, _miners, _structuredLogging)); + m_ethereum.reset(new eth::Client(&m_net, _dbPath, _forceClean, 0, _miners, _structuredLogger)); if (_interfaces.count("shh")) m_whisper = m_net.registerCapability(new WhisperHost); diff --git a/libwebthree/WebThree.h b/libwebthree/WebThree.h index 03adbd727..840e91b2b 100644 --- a/libwebthree/WebThree.h +++ b/libwebthree/WebThree.h @@ -106,7 +106,7 @@ public: WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean = false, std::set const& _interfaces = {"eth", "shh"}, p2p::NetworkPreferences const& _n = p2p::NetworkPreferences(), - bytesConstRef _network = bytesConstRef(), int _miners = -1, bool _structuredLogging = false); + bytesConstRef _network = bytesConstRef(), int _miners = -1, StructuredLogger const* _structuredLogger = nullptr); /// Destructor. ~WebThreeDirect(); From ba814939763b817172e162f89fc49f2a3a414f7a Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Sat, 28 Feb 2015 23:51:27 +0100 Subject: [PATCH 15/54] StructuredLogger propagated as a const reference --- libdevcore/StructuredLogger.h | 1 + libethereum/BlockChain.cpp | 33 +++++++++++++++------------------ libethereum/BlockChain.h | 8 ++++---- libethereum/Client.cpp | 8 +++----- libethereum/Client.h | 7 +++---- libethereum/EthereumHost.cpp | 6 ++---- libethereum/EthereumHost.h | 3 +-- libp2p/Host.cpp | 8 +++----- libp2p/Host.h | 7 +++---- libwebthree/WebThree.cpp | 2 +- libwebthree/WebThree.h | 2 +- 11 files changed, 37 insertions(+), 48 deletions(-) diff --git a/libdevcore/StructuredLogger.h b/libdevcore/StructuredLogger.h index 8d807d9d4..de838da6f 100644 --- a/libdevcore/StructuredLogger.h +++ b/libdevcore/StructuredLogger.h @@ -35,6 +35,7 @@ namespace dev class StructuredLogger { public: + StructuredLogger(): m_enabled(false) {} StructuredLogger(bool _enabled): m_enabled(_enabled) {} void logStarting(std::string const& _clientImpl, const char* _ethVersion); diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 0ac9445d7..6cce7b51b 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -153,7 +152,7 @@ inline string toString(h256s const& _bs) return out.str(); } -h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max, StructuredLogger const* _logger) +h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max, StructuredLogger const& _logger) { _bq.tick(*this); @@ -188,7 +187,7 @@ h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max return ret; } -h256s BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, StructuredLogger const* _logger) noexcept +h256s BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, StructuredLogger const& _logger) noexcept { try { @@ -201,7 +200,7 @@ h256s BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, } } -h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, StructuredLogger const* _logger) +h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, StructuredLogger const& _logger) { // VERIFY: populates from the block and checks the block is internally coherent. BlockInfo bi; @@ -318,13 +317,12 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, StructuredLo } #endif - if (_logger) - _logger->logChainReceivedNewBlock( - bi.headerHash(WithoutNonce).abridged(), - bi.nonce.abridged(), - currentHash().abridged(), - "", // TODO: remote id ?? - bi.parentHash.abridged()); + _logger.logChainReceivedNewBlock( + bi.headerHash(WithoutNonce).abridged(), + bi.nonce.abridged(), + currentHash().abridged(), + "", // TODO: remote id ?? + bi.parentHash.abridged()); // cnote << "Parent " << bi.parentHash << " has " << details(bi.parentHash).children.size() << " children."; h256s ret; @@ -339,13 +337,12 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, StructuredLo } m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&newHash, 32)); clog(BlockChainNote) << " Imported and best" << td << ". Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(ret); - if (_logger) - _logger->logChainNewHead( - bi.headerHash(WithoutNonce).abridged(), - bi.nonce.abridged(), - currentHash().abridged(), - bi.parentHash.abridged() - ); + _logger.logChainNewHead( + bi.headerHash(WithoutNonce).abridged(), + bi.nonce.abridged(), + currentHash().abridged(), + bi.parentHash.abridged() + ); } else { diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index dc0cd76b2..ffdbccee4 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -32,6 +32,7 @@ #include #include #include +#include #include "BlockDetails.h" #include "Account.h" #include "BlockQueue.h" @@ -40,7 +41,6 @@ namespace ldb = leveldb; namespace dev { -class StructuredLogger; class OverlayDB; namespace eth @@ -80,15 +80,15 @@ public: void process(); /// Sync the chain with any incoming blocks. All blocks should, if processed in order - h256s sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max, StructuredLogger const* _logger); + h256s sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max, StructuredLogger const& _logger); /// Attempt to import the given block directly into the CanonBlockChain and sync with the state DB. /// @returns the block hashes of any blocks that came into/went out of the canonical block chain. - h256s attemptImport(bytes const& _block, OverlayDB const& _stateDB, StructuredLogger const* _logger = nullptr) noexcept; + h256s attemptImport(bytes const& _block, OverlayDB const& _stateDB, StructuredLogger const& _logger = StructuredLogger()) noexcept; /// Import block into disk-backed DB /// @returns the block hashes of any blocks that came into/went out of the canonical block chain. - h256s import(bytes const& _block, OverlayDB const& _stateDB, StructuredLogger const* _logger = nullptr); + h256s import(bytes const& _block, OverlayDB const& _stateDB, StructuredLogger const& _logger = StructuredLogger()); /// Returns true if the given block is known (though not necessarily a part of the canon chain). bool isKnown(h256 _hash) const; diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 6c9c1c44e..a4e9c9a66 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include "Defaults.h" #include "Executive.h" @@ -61,7 +60,7 @@ void VersionChecker::setOk() } Client::Client(p2p::Host* _extNet, std::string const& _dbPath, bool _forceClean, - u256 _networkId, int _miners, StructuredLogger const* _structuredLogger): + u256 _networkId, int _miners, StructuredLogger const& _structuredLogger): Worker("eth"), m_vc(_dbPath), m_bc(_dbPath, !m_vc.ok() || _forceClean), @@ -70,7 +69,7 @@ Client::Client(p2p::Host* _extNet, std::string const& _dbPath, bool _forceClean, m_postMine(Address(), m_stateDB), m_structuredLogger(_structuredLogger) { - m_host = _extNet->registerCapability(new EthereumHost(m_bc, m_tq, m_bq, _networkId, _structuredLogger)); + m_host = _extNet->registerCapability(new EthereumHost(m_bc, m_tq, m_bq, _networkId)); if (_miners > -1) setMiningThreads(_miners); @@ -418,8 +417,7 @@ void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _ } Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); // cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); - if (m_structuredLogger) - m_structuredLogger->logTransactionReceived(t.sha3().abridged(), t.sender().abridged()); + m_structuredLogger.logTransactionReceived(t.sha3().abridged(), t.sender().abridged()); cnote << "New transaction " << t; m_tq.attemptImport(t.rlp()); } diff --git a/libethereum/Client.h b/libethereum/Client.h index 644a6ed6c..33b0080f2 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include "CanonBlockChain.h" @@ -45,8 +46,6 @@ namespace dev { -class StructuredLogger; - namespace eth { @@ -170,7 +169,7 @@ class Client: public MinerHost, public Interface, Worker public: /// New-style Constructor. explicit Client(p2p::Host* _host, std::string const& _dbPath = std::string(), bool _forceClean = false, - u256 _networkId = 0, int _miners = -1, StructuredLogger const* _structuredLogger = nullptr); + u256 _networkId = 0, int _miners = -1, StructuredLogger const& _structuredLogger = StructuredLogger()); /// Destructor. virtual ~Client(); @@ -368,7 +367,7 @@ private: std::map m_filters; std::map m_watches; - StructuredLogger const* m_structuredLogger; + StructuredLogger const& m_structuredLogger; mutable std::chrono::system_clock::time_point m_lastGarbageCollection; }; diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 4d605a209..7dfc51b47 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -38,15 +38,13 @@ using namespace dev; using namespace dev::eth; using namespace p2p; -EthereumHost::EthereumHost(BlockChain const& _ch, TransactionQueue& _tq, BlockQueue& _bq, - u256 _networkId, bool _structuredLogging): +EthereumHost::EthereumHost(BlockChain const& _ch, TransactionQueue& _tq, BlockQueue& _bq, u256 _networkId): HostCapability(), Worker ("ethsync"), m_chain (_ch), m_tq (_tq), m_bq (_bq), - m_networkId (_networkId), - m_structuredLogging (_structuredLogging) + m_networkId (_networkId) { m_latestBlockSent = _ch.currentHash(); } diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index c9f92d1e0..dfa928675 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -59,7 +59,7 @@ class EthereumHost: public p2p::HostCapability, Worker public: /// Start server, but don't listen. - EthereumHost(BlockChain const& _ch, TransactionQueue& _tq, BlockQueue& _bq, u256 _networkId, bool _structuredLogging); + EthereumHost(BlockChain const& _ch, TransactionQueue& _tq, BlockQueue& _bq, u256 _networkId); /// Will block on network process events. virtual ~EthereumHost(); @@ -111,7 +111,6 @@ private: u256 m_networkId; EthereumPeer* m_syncer = nullptr; // TODO: switch to weak_ptr - bool m_structuredLogging; DownloadMan m_man; diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 97d785dc6..9c73f0173 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include "Session.h" @@ -46,7 +45,7 @@ void HostNodeTableHandler::processEvent(NodeId const& _n, NodeTableEventType con m_host.onNodeTableEvent(_n, _e); } -Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bytesConstRef _restoreNetwork, StructuredLogger const* _structuredLogger): +Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bytesConstRef _restoreNetwork, StructuredLogger const& _structuredLogger): Worker("p2p", 0), m_restoreNetwork(_restoreNetwork.toBytes()), m_clientVersion(_clientVersion), @@ -477,9 +476,8 @@ void Host::connect(std::shared_ptr const& _p) _p->m_lastConnected = std::chrono::system_clock::now(); _p->m_failedAttempts = 0; - if (m_structuredLogger) - m_structuredLogger->logP2PConnected(_p->id.abridged(), _p->peerEndpoint(), _p->m_lastConnected, - 0);// TODO: num_connections + m_structuredLogger.logP2PConnected(_p->id.abridged(), _p->peerEndpoint(), _p->m_lastConnected, + 0);// TODO: num_connections auto ps = make_shared(this, std::move(*s), _p); ps->start(); diff --git a/libp2p/Host.h b/libp2p/Host.h index b93a64556..de984ca59 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "NodeTable.h" #include "HostCapability.h" @@ -45,8 +46,6 @@ namespace bi = ba::ip; namespace dev { -class StructuredLogger; - namespace p2p { @@ -88,7 +87,7 @@ class Host: public Worker public: /// Start server, listening for connections on the given port. Host(std::string const& _clientVersion, NetworkPreferences const& _n = NetworkPreferences(), - bytesConstRef _restoreNetwork = bytesConstRef(), StructuredLogger const* _structuredLogger = nullptr); + bytesConstRef _restoreNetwork = bytesConstRef(), StructuredLogger const& _structuredLogger = StructuredLogger()); /// Will block on network process events. virtual ~Host(); @@ -235,7 +234,7 @@ private: std::map> m_capabilities; ///< Each of the capabilities we support. std::chrono::steady_clock::time_point m_lastPing; ///< Time we sent the last ping to all peers. - StructuredLogger const* m_structuredLogger; + StructuredLogger const& m_structuredLogger; bool m_accepting = false; }; diff --git a/libwebthree/WebThree.cpp b/libwebthree/WebThree.cpp index 1025aad55..50e988932 100644 --- a/libwebthree/WebThree.cpp +++ b/libwebthree/WebThree.cpp @@ -37,7 +37,7 @@ using namespace dev::shh; WebThreeDirect::WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean, std::set const& _interfaces, NetworkPreferences const& _n, - bytesConstRef _network, int _miners, StructuredLogger const* _structuredLogger): + bytesConstRef _network, int _miners, StructuredLogger const& _structuredLogger): m_clientVersion(_clientVersion), m_net(_clientVersion, _n, _network, _structuredLogger) { diff --git a/libwebthree/WebThree.h b/libwebthree/WebThree.h index 840e91b2b..197181335 100644 --- a/libwebthree/WebThree.h +++ b/libwebthree/WebThree.h @@ -106,7 +106,7 @@ public: WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean = false, std::set const& _interfaces = {"eth", "shh"}, p2p::NetworkPreferences const& _n = p2p::NetworkPreferences(), - bytesConstRef _network = bytesConstRef(), int _miners = -1, StructuredLogger const* _structuredLogger = nullptr); + bytesConstRef _network = bytesConstRef(), int _miners = -1, StructuredLogger const& _structuredLogger = StructuredLogger()); /// Destructor. ~WebThreeDirect(); From 643499e4913f924baedcce0cabc409be91e6428d Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Sun, 1 Mar 2015 00:13:33 +0100 Subject: [PATCH 16/54] Add p2p disconnected structured log event --- libdevcore/StructuredLogger.cpp | 2 +- libdevcore/StructuredLogger.h | 2 +- libethereum/BlockChain.h | 2 +- libp2p/Host.cpp | 7 ++++--- libp2p/Session.cpp | 2 ++ 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libdevcore/StructuredLogger.cpp b/libdevcore/StructuredLogger.cpp index 458f3dc79..8188b0d04 100644 --- a/libdevcore/StructuredLogger.cpp +++ b/libdevcore/StructuredLogger.cpp @@ -80,7 +80,7 @@ void StructuredLogger::logP2PConnected(string const& _id, bi::tcp::endpoint cons } } -void StructuredLogger::logP2PDisconnected(string const& _id, unsigned int _numConnections, bi::tcp::endpoint const& _addr) const +void StructuredLogger::logP2PDisconnected(string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections) const { if (m_enabled) { diff --git a/libdevcore/StructuredLogger.h b/libdevcore/StructuredLogger.h index de838da6f..b3a71430f 100644 --- a/libdevcore/StructuredLogger.h +++ b/libdevcore/StructuredLogger.h @@ -41,7 +41,7 @@ public: void logStarting(std::string const& _clientImpl, const char* _ethVersion); void logP2PConnected(std::string const& _id, bi::tcp::endpoint const& _addr, std::chrono::system_clock::time_point const& _ts, unsigned int _numConnections) const; - void logP2PDisconnected(std::string const& _id, unsigned int _numConnections, bi::tcp::endpoint const& _addr) const; + void logP2PDisconnected(std::string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections) const; void logMinedNewBlock(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, std::string const& _prevHash) const; void logChainReceivedNewBlock(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index ffdbccee4..6d36b14cd 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -97,7 +97,7 @@ public: BlockInfo info(h256 _hash) const { return BlockInfo(block(_hash)); } BlockInfo info() const { return BlockInfo(block()); } - /// Get the familial details concerning a block (or the most recent mined if none given). Thread-safe. + /// Get the familiar details concerning a block (or the most recent mined if none given). Thread-safe. BlockDetails details(h256 _hash) const { return queryExtras(_hash, m_details, x_details, NullBlockDetails); } BlockDetails details() const { return details(currentHash()); } diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 9c73f0173..5b35f4ca7 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -159,6 +159,10 @@ void Host::registerPeer(std::shared_ptr _s, CapDescs const& _caps) { { clog(NetNote) << "p2p.host.peer.register" << _s->m_peer->id.abridged(); + m_structuredLogger.logP2PConnected( + _s->m_peer->id.abridged(), _s->m_peer->peerEndpoint(), + _s->m_peer->m_lastConnected, + 0);// TODO: num_connections RecursiveGuard l(x_sessions); // TODO: temporary loose-coupling; if m_peers already has peer, // it is same as _s->m_peer. (fixing next PR) @@ -476,9 +480,6 @@ void Host::connect(std::shared_ptr const& _p) _p->m_lastConnected = std::chrono::system_clock::now(); _p->m_failedAttempts = 0; - m_structuredLogger.logP2PConnected(_p->id.abridged(), _p->peerEndpoint(), _p->m_lastConnected, - 0);// TODO: num_connections - auto ps = make_shared(this, std::move(*s), _p); ps->start(); diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp index 6ff765cf6..78caa6273 100644 --- a/libp2p/Session.cpp +++ b/libp2p/Session.cpp @@ -467,6 +467,8 @@ void Session::drop(DisconnectReason _reason) void Session::disconnect(DisconnectReason _reason) { clogS(NetConnect) << "Disconnecting (our reason:" << reasonOf(_reason) << ")"; + m_server->m_structuredLogger.logP2PDisconnected(m_info.id.abridged(), m_peer->peerEndpoint(), + 0);// TODO: num connections if (m_socket.is_open()) { RLPStream s; From 6c4faef7327ecc2488f9ce329f406db7f9867f4d Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Sun, 1 Mar 2015 00:20:09 +0100 Subject: [PATCH 17/54] Add remote version to p2pconnected log event --- libdevcore/StructuredLogger.cpp | 4 ++-- libdevcore/StructuredLogger.h | 10 ++++++---- libp2p/Host.cpp | 1 + 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libdevcore/StructuredLogger.cpp b/libdevcore/StructuredLogger.cpp index 8188b0d04..1114755ec 100644 --- a/libdevcore/StructuredLogger.cpp +++ b/libdevcore/StructuredLogger.cpp @@ -62,14 +62,14 @@ void StructuredLogger::logStarting(string const& _clientImpl, const char* _ethVe } void StructuredLogger::logP2PConnected(string const& _id, bi::tcp::endpoint const& _addr, - chrono::system_clock::time_point const& _ts, unsigned int _numConnections) const + chrono::system_clock::time_point const& _ts, string const& _remoteVersion, unsigned int _numConnections) const { if (m_enabled) { std::stringstream addrStream; addrStream << _addr; Json::Value event; - event["remote_version_string"] = ""; //TODO + event["remote_version_string"] = _remoteVersion; event["comment"] = "as soon as a successful connection to another node is established"; event["remote_addr"] = addrStream.str(); event["remote_id"] = _id; diff --git a/libdevcore/StructuredLogger.h b/libdevcore/StructuredLogger.h index b3a71430f..739aef274 100644 --- a/libdevcore/StructuredLogger.h +++ b/libdevcore/StructuredLogger.h @@ -19,6 +19,8 @@ * @date 2015 * * A simple helper class for the structured logging + * The spec for the implemented log events is here: + * https://github.com/ethereum/system-testing/wiki/Log-Events */ #pragma once @@ -40,14 +42,14 @@ public: void logStarting(std::string const& _clientImpl, const char* _ethVersion); void logP2PConnected(std::string const& _id, bi::tcp::endpoint const& _addr, - std::chrono::system_clock::time_point const& _ts, unsigned int _numConnections) const; + std::chrono::system_clock::time_point const& _ts, std::string const& _remoteVersion, unsigned int _numConnections) const; void logP2PDisconnected(std::string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections) const; void logMinedNewBlock(std::string const& _hash, std::string const& _blockNumber, - std::string const& _chainHeadHash, std::string const& _prevHash) const; + std::string const& _chainHeadHash, std::string const& _prevHash) const; void logChainReceivedNewBlock(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, - std::string const& _remoteID, std::string const& _prevHash) const; + std::string const& _remoteID, std::string const& _prevHash) const; void logChainNewHead(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, - std::string const& _prevHash) const; + std::string const& _prevHash) const; void logTransactionReceived(std::string const& _hash, std::string const& _remoteId) const; private: /// @returns a string representation of a timepoint diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 5b35f4ca7..ffc726db8 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -162,6 +162,7 @@ void Host::registerPeer(std::shared_ptr _s, CapDescs const& _caps) m_structuredLogger.logP2PConnected( _s->m_peer->id.abridged(), _s->m_peer->peerEndpoint(), _s->m_peer->m_lastConnected, + _s->m_info.clientVersion, 0);// TODO: num_connections RecursiveGuard l(x_sessions); // TODO: temporary loose-coupling; if m_peers already has peer, From 063a12fd8824042d9bcce1d6aa87ed5476c7c1ce Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Sun, 1 Mar 2015 01:23:31 +0100 Subject: [PATCH 18/54] Structured logging should now work for some events --- eth/main.cpp | 9 +++---- libdevcore/StructuredLogger.cpp | 45 ++++++++++++++++++--------------- libdevcore/StructuredLogger.h | 14 +++++----- 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 938bf936b..0beafc199 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -282,7 +282,7 @@ int main(int argc, char** argv) } else if ((arg == "-s" || arg == "--secret") && i + 1 < argc) us = KeyPair(h256(fromHex(argv[++i]))); - else if ((arg == "--structured-logging") && i + 1 < argc) + else if (arg == "--structured-logging") structuredLogging = true; else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc) dbPath = argv[++i]; @@ -355,7 +355,7 @@ int main(int argc, char** argv) cout << credits(); - unique_ptr structuredLogger(new StructuredLogger(structuredLogging)); + StructuredLogger structuredLogger(structuredLogging); VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter); NetworkPreferences netPrefs(listenPort, publicIP, upnp, useLocal); auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp"); @@ -368,12 +368,11 @@ int main(int argc, char** argv) netPrefs, &nodesState, miners, - structuredLogger.get() + structuredLogger ); web3.setIdealPeerCount(peers); eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr; - if (structuredLogging) - structuredLogger->logStarting(clientImplString, dev::Version); + structuredLogger.logStarting(clientImplString, dev::Version); if (c) { c->setForceMining(forceMining); diff --git a/libdevcore/StructuredLogger.cpp b/libdevcore/StructuredLogger.cpp index 1114755ec..09d9af310 100644 --- a/libdevcore/StructuredLogger.cpp +++ b/libdevcore/StructuredLogger.cpp @@ -23,6 +23,7 @@ #include "StructuredLogger.h" +#include #include using namespace std; @@ -30,34 +31,38 @@ using namespace std; namespace dev { -char const* StructuredLogger::timePointToString(chrono::system_clock::time_point const& _ts) const +string StructuredLogger::timePointToString(chrono::system_clock::time_point const& _ts) const { // not using C++11 std::put_time due to gcc bug // http://stackoverflow.com/questions/14136833/stdput-time-implementation-status-in-gcc // TODO: Format it according to Log event Requirements + char buffer[64]; time_t time = chrono::system_clock::to_time_t(_ts); - return ctime(&time); + tm* ptm = localtime(&time); + if (strftime(buffer, sizeof(buffer), m_timeFormat.c_str(), ptm)) + return string(buffer); + return ""; } -void StructuredLogger::outputJson(Json::Value const* _value, std::string const& _name) const +void StructuredLogger::outputJson(Json::Value const& _value, std::string const& _name) const { Json::Value event; event[_name] = _value; - cout << event; + cout << event << endl; } -void StructuredLogger::logStarting(string const& _clientImpl, const char* _ethVersion) +void StructuredLogger::logStarting(string const& _clientImpl, const char* _ethVersion) const { if (m_enabled) { Json::Value event; event["comment"] = "one of the first log events, before any operation is started"; - event["client_implt"] = _clientImpl; + event["client_impl"] = _clientImpl; event["eth_version"] = std::string(_ethVersion); - event["ts"] = string(timePointToString(std::chrono::system_clock::now())); + event["ts"] = timePointToString(std::chrono::system_clock::now()); - outputJson(&event, "starting"); + outputJson(event, "starting"); } } @@ -74,9 +79,9 @@ void StructuredLogger::logP2PConnected(string const& _id, bi::tcp::endpoint cons event["remote_addr"] = addrStream.str(); event["remote_id"] = _id; event["num_connections"] = Json::Value(_numConnections); - event["ts"] = string(timePointToString(_ts)); + event["ts"] = timePointToString(_ts); - outputJson(&event, "p2p.connected"); + outputJson(event, "p2p.connected"); } } @@ -91,9 +96,9 @@ void StructuredLogger::logP2PDisconnected(string const& _id, bi::tcp::endpoint c event["remote_addr"] = addrStream.str(); event["remote_id"] = _id; event["num_connections"] = Json::Value(_numConnections); - event["ts"] = string(timePointToString(chrono::system_clock::now())); + event["ts"] = timePointToString(chrono::system_clock::now()); - outputJson(&event, "p2p.disconnected"); + outputJson(event, "p2p.disconnected"); } } @@ -107,10 +112,10 @@ void StructuredLogger::logMinedNewBlock(string const& _hash, string const& _bloc event["block_hash"] = _hash; event["block_number"] = _blockNumber; event["chain_head_hash"] = _chainHeadHash; - event["ts"] = string(timePointToString(std::chrono::system_clock::now())); + event["ts"] = timePointToString(std::chrono::system_clock::now()); event["block_prev_hash"] = _prevHash; - outputJson(&event, "eth.miner.new_block"); + outputJson(event, "eth.miner.new_block"); } } @@ -125,10 +130,10 @@ void StructuredLogger::logChainReceivedNewBlock(string const& _hash, string cons event["block_number"] = _blockNumber; event["chain_head_hash"] = _chainHeadHash; event["remote_id"] = _remoteID; - event["ts"] = string(timePointToString(chrono::system_clock::now())); + event["ts"] = timePointToString(chrono::system_clock::now()); event["block_prev_hash"] = _prevHash; - outputJson(&event, "eth.chain.received.new_block"); + outputJson(event, "eth.chain.received.new_block"); } } @@ -142,10 +147,10 @@ void StructuredLogger::logChainNewHead(string const& _hash, string const& _block event["block_hash"] = _hash; event["block_number"] = _blockNumber; event["chain_head_hash"] = _chainHeadHash; - event["ts"] = string(timePointToString(chrono::system_clock::now())); + event["ts"] = timePointToString(chrono::system_clock::now()); event["block_prev_hash"] = _prevHash; - outputJson(&event, "eth.miner.new_block"); + outputJson(event, "eth.miner.new_block"); } } @@ -156,9 +161,9 @@ void StructuredLogger::logTransactionReceived(string const& _hash, string const& Json::Value event; event["tx_hash"] = _hash; event["remote_id"] = _remoteId; - event["ts"] = string(timePointToString(chrono::system_clock::now())); + event["ts"] = timePointToString(chrono::system_clock::now()); - outputJson(&event, "eth.tx.received"); + outputJson(event, "eth.tx.received"); } } diff --git a/libdevcore/StructuredLogger.h b/libdevcore/StructuredLogger.h index 739aef274..ae4d52c33 100644 --- a/libdevcore/StructuredLogger.h +++ b/libdevcore/StructuredLogger.h @@ -37,10 +37,11 @@ namespace dev class StructuredLogger { public: - StructuredLogger(): m_enabled(false) {} - StructuredLogger(bool _enabled): m_enabled(_enabled) {} + StructuredLogger(): m_enabled(false){} + StructuredLogger(bool _enabled, std::string const& _timeFormat = "%Y-%m-%dT%H:%M:%S"): + m_enabled(_enabled), m_timeFormat(_timeFormat) {} - void logStarting(std::string const& _clientImpl, const char* _ethVersion); + void logStarting(std::string const& _clientImpl, const char* _ethVersion) const; void logP2PConnected(std::string const& _id, bi::tcp::endpoint const& _addr, std::chrono::system_clock::time_point const& _ts, std::string const& _remoteVersion, unsigned int _numConnections) const; void logP2PDisconnected(std::string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections) const; @@ -53,10 +54,11 @@ public: void logTransactionReceived(std::string const& _hash, std::string const& _remoteId) const; private: /// @returns a string representation of a timepoint - char const* timePointToString(std::chrono::system_clock::time_point const& _ts) const; - void outputJson(Json::Value const* _value, std::string const& _name) const; - bool m_enabled; + std::string timePointToString(std::chrono::system_clock::time_point const& _ts) const; + void outputJson(Json::Value const& _value, std::string const& _name) const; + bool m_enabled; + std::string m_timeFormat = "%Y-%m-%dT%H:%M:%S"; }; } From 97ab2d6d18ea4ac597d9d73eecbc56606f2d2afd Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Sun, 1 Mar 2015 01:36:08 +0100 Subject: [PATCH 19/54] StructuredLogging timestamp format is now configurable --- eth/main.cpp | 6 +++++- libdevcore/StructuredLogger.h | 13 +++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 0beafc199..6f22dcd91 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -121,6 +121,7 @@ void help() << " -r,--remote Connect to remote host (default: none)." << endl << " -s,--secret Set the secret key for use with send command (default: auto)." << endl << " --structured-logging Enables structured logging." << endl + << " --structured-logging-format Give time format string for structured logging output." << endl << " -t,--miners Number of mining threads to start (Default: " << thread::hardware_concurrency() << ")" << endl << " -u,--public-ip Force public ip to given (default; auto)." << endl << " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (Default: 8)." << endl @@ -210,6 +211,7 @@ int main(int argc, char** argv) bool forceMining = false; bool jit = false; bool structuredLogging = false; + string structuredLoggingFormat = "%Y-%m-%dT%H:%M:%S"; string clientName; // Init defaults @@ -282,6 +284,8 @@ int main(int argc, char** argv) } else if ((arg == "-s" || arg == "--secret") && i + 1 < argc) us = KeyPair(h256(fromHex(argv[++i]))); + else if (arg == "--structured-logging-format" && i + 1 < argc) + structuredLoggingFormat = string(argv[++i]); else if (arg == "--structured-logging") structuredLogging = true; else if ((arg == "-d" || arg == "--path" || arg == "--db-path") && i + 1 < argc) @@ -355,7 +359,7 @@ int main(int argc, char** argv) cout << credits(); - StructuredLogger structuredLogger(structuredLogging); + StructuredLogger structuredLogger(structuredLogging, structuredLoggingFormat); VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter); NetworkPreferences netPrefs(listenPort, publicIP, upnp, useLocal); auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp"); diff --git a/libdevcore/StructuredLogger.h b/libdevcore/StructuredLogger.h index ae4d52c33..54dcc7975 100644 --- a/libdevcore/StructuredLogger.h +++ b/libdevcore/StructuredLogger.h @@ -34,12 +34,21 @@ namespace Json { class Value; } namespace dev { +// TODO: Make the output stream configurable. stdout, stderr, file e.t.c. class StructuredLogger { public: + /// Default constructor, logging off StructuredLogger(): m_enabled(false){} - StructuredLogger(bool _enabled, std::string const& _timeFormat = "%Y-%m-%dT%H:%M:%S"): - m_enabled(_enabled), m_timeFormat(_timeFormat) {} + /** + * Initializes a structured logger object + * @param _enabled Whether logging is on or off + * @param _timeFormat A time format string as described here: + * http://en.cppreference.com/w/cpp/chrono/c/strftime + * with which to display timestamps + */ + StructuredLogger(bool _enabled, std::string const& _timeFormat): + m_enabled(_enabled), m_timeFormat(_timeFormat) {} void logStarting(std::string const& _clientImpl, const char* _ethVersion) const; void logP2PConnected(std::string const& _id, bi::tcp::endpoint const& _addr, From afaac3f5113dc172097df47b876cececdd552fb1 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Sun, 1 Mar 2015 01:41:43 +0100 Subject: [PATCH 20/54] Adding a StructuredLogging stop event --- eth/main.cpp | 1 + libdevcore/StructuredLogger.cpp | 14 ++++++++++++++ libdevcore/StructuredLogger.h | 1 + 3 files changed, 16 insertions(+) diff --git a/eth/main.cpp b/eth/main.cpp index 6f22dcd91..a4a35779c 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -910,6 +910,7 @@ int main(int argc, char** argv) while (!g_exit) this_thread::sleep_for(chrono::milliseconds(1000)); + structuredLogger.logStopping(clientImplString, dev::Version); auto netData = web3.saveNetwork(); if (!netData.empty()) writeFile((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp", netData); diff --git a/libdevcore/StructuredLogger.cpp b/libdevcore/StructuredLogger.cpp index 09d9af310..2bd208624 100644 --- a/libdevcore/StructuredLogger.cpp +++ b/libdevcore/StructuredLogger.cpp @@ -66,6 +66,20 @@ void StructuredLogger::logStarting(string const& _clientImpl, const char* _ethVe } } +void StructuredLogger::logStopping(string const& _clientImpl, const char* _ethVersion) const +{ + if (m_enabled) + { + Json::Value event; + event["comment"] = "last event before termination of the client"; + event["client_impl"] = _clientImpl; + event["eth_version"] = std::string(_ethVersion); + event["ts"] = timePointToString(std::chrono::system_clock::now()); + + outputJson(event, "stopping"); + } +} + void StructuredLogger::logP2PConnected(string const& _id, bi::tcp::endpoint const& _addr, chrono::system_clock::time_point const& _ts, string const& _remoteVersion, unsigned int _numConnections) const { diff --git a/libdevcore/StructuredLogger.h b/libdevcore/StructuredLogger.h index 54dcc7975..7fbde7c5a 100644 --- a/libdevcore/StructuredLogger.h +++ b/libdevcore/StructuredLogger.h @@ -51,6 +51,7 @@ public: m_enabled(_enabled), m_timeFormat(_timeFormat) {} void logStarting(std::string const& _clientImpl, const char* _ethVersion) const; + void logStopping(std::string const& _clientImpl, const char* _ethVersion) const; void logP2PConnected(std::string const& _id, bi::tcp::endpoint const& _addr, std::chrono::system_clock::time_point const& _ts, std::string const& _remoteVersion, unsigned int _numConnections) const; void logP2PDisconnected(std::string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections) const; From d3ce888c0b8a943bc26b503fef23c57e1f65a74c Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 2 Mar 2015 11:48:23 +0100 Subject: [PATCH 21/54] Adding a mutex to StructuredLogger --- libdevcore/StructuredLogger.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/libdevcore/StructuredLogger.cpp b/libdevcore/StructuredLogger.cpp index 2bd208624..4121f7cc2 100644 --- a/libdevcore/StructuredLogger.cpp +++ b/libdevcore/StructuredLogger.cpp @@ -25,6 +25,7 @@ #include #include +#include "Guards.h" using namespace std; @@ -36,7 +37,6 @@ string StructuredLogger::timePointToString(chrono::system_clock::time_point cons // not using C++11 std::put_time due to gcc bug // http://stackoverflow.com/questions/14136833/stdput-time-implementation-status-in-gcc - // TODO: Format it according to Log event Requirements char buffer[64]; time_t time = chrono::system_clock::to_time_t(_ts); tm* ptm = localtime(&time); @@ -48,8 +48,10 @@ string StructuredLogger::timePointToString(chrono::system_clock::time_point cons void StructuredLogger::outputJson(Json::Value const& _value, std::string const& _name) const { Json::Value event; + static Mutex s_lock; + Guard l(s_lock); event[_name] = _value; - cout << event << endl; + cout << event << endl << flush; } void StructuredLogger::logStarting(string const& _clientImpl, const char* _ethVersion) const @@ -57,7 +59,6 @@ void StructuredLogger::logStarting(string const& _clientImpl, const char* _ethVe if (m_enabled) { Json::Value event; - event["comment"] = "one of the first log events, before any operation is started"; event["client_impl"] = _clientImpl; event["eth_version"] = std::string(_ethVersion); event["ts"] = timePointToString(std::chrono::system_clock::now()); @@ -71,7 +72,6 @@ void StructuredLogger::logStopping(string const& _clientImpl, const char* _ethVe if (m_enabled) { Json::Value event; - event["comment"] = "last event before termination of the client"; event["client_impl"] = _clientImpl; event["eth_version"] = std::string(_ethVersion); event["ts"] = timePointToString(std::chrono::system_clock::now()); @@ -89,7 +89,6 @@ void StructuredLogger::logP2PConnected(string const& _id, bi::tcp::endpoint cons addrStream << _addr; Json::Value event; event["remote_version_string"] = _remoteVersion; - event["comment"] = "as soon as a successful connection to another node is established"; event["remote_addr"] = addrStream.str(); event["remote_id"] = _id; event["num_connections"] = Json::Value(_numConnections); @@ -106,7 +105,6 @@ void StructuredLogger::logP2PDisconnected(string const& _id, bi::tcp::endpoint c std::stringstream addrStream; addrStream << _addr; Json::Value event; - event["comment"] = "as soon as a disconnection from another node happened"; event["remote_addr"] = addrStream.str(); event["remote_id"] = _id; event["num_connections"] = Json::Value(_numConnections); @@ -122,7 +120,6 @@ void StructuredLogger::logMinedNewBlock(string const& _hash, string const& _bloc if (m_enabled) { Json::Value event; - event["comment"] = "as soon as the block was mined, before adding as new head"; event["block_hash"] = _hash; event["block_number"] = _blockNumber; event["chain_head_hash"] = _chainHeadHash; @@ -139,7 +136,6 @@ void StructuredLogger::logChainReceivedNewBlock(string const& _hash, string cons if (m_enabled) { Json::Value event; - event["comment"] = "whenever a _new_ block is received, before adding"; event["block_hash"] = _hash; event["block_number"] = _blockNumber; event["chain_head_hash"] = _chainHeadHash; @@ -157,7 +153,6 @@ void StructuredLogger::logChainNewHead(string const& _hash, string const& _block if (m_enabled) { Json::Value event; - event["comment"] = "whenever head changes"; event["block_hash"] = _hash; event["block_number"] = _blockNumber; event["chain_head_hash"] = _chainHeadHash; From 623d640fb53210502d5fabfa9189dba3498ae722 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 2 Mar 2015 13:38:02 +0100 Subject: [PATCH 22/54] StructuredLogger becomes a global singleton class --- eth/main.cpp | 9 ++++---- libdevcore/StructuredLogger.cpp | 16 ++++++------- libdevcore/StructuredLogger.h | 41 ++++++++++++++++++++++----------- libethereum/BlockChain.cpp | 15 ++++++------ libethereum/BlockChain.h | 7 +++--- libethereum/Client.cpp | 13 +++++------ libethereum/Client.h | 4 +--- libethereum/Miner.cpp | 5 ++-- libethereum/Miner.h | 4 +--- libethereum/State.cpp | 17 +++++++------- libethereum/State.h | 4 +--- libp2p/Host.cpp | 8 +++---- libp2p/Host.h | 4 +--- libp2p/Session.cpp | 7 ++++-- libwebthree/WebThree.cpp | 6 ++--- libwebthree/WebThree.h | 2 +- 16 files changed, 84 insertions(+), 78 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index a4a35779c..fa78a4190 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -359,7 +359,7 @@ int main(int argc, char** argv) cout << credits(); - StructuredLogger structuredLogger(structuredLogging, structuredLoggingFormat); + StructLog.initialize(structuredLogging, structuredLoggingFormat); VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter); NetworkPreferences netPrefs(listenPort, publicIP, upnp, useLocal); auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp"); @@ -371,12 +371,11 @@ int main(int argc, char** argv) mode == NodeMode::Full ? set{"eth", "shh"} : set(), netPrefs, &nodesState, - miners, - structuredLogger + miners ); web3.setIdealPeerCount(peers); eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr; - structuredLogger.logStarting(clientImplString, dev::Version); + StructLog.starting(clientImplString, dev::Version); if (c) { c->setForceMining(forceMining); @@ -910,7 +909,7 @@ int main(int argc, char** argv) while (!g_exit) this_thread::sleep_for(chrono::milliseconds(1000)); - structuredLogger.logStopping(clientImplString, dev::Version); + StructLog.stopping(clientImplString, dev::Version); auto netData = web3.saveNetwork(); if (!netData.empty()) writeFile((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp", netData); diff --git a/libdevcore/StructuredLogger.cpp b/libdevcore/StructuredLogger.cpp index 4121f7cc2..5fd605e3a 100644 --- a/libdevcore/StructuredLogger.cpp +++ b/libdevcore/StructuredLogger.cpp @@ -54,7 +54,7 @@ void StructuredLogger::outputJson(Json::Value const& _value, std::string const& cout << event << endl << flush; } -void StructuredLogger::logStarting(string const& _clientImpl, const char* _ethVersion) const +void StructuredLogger::starting(string const& _clientImpl, const char* _ethVersion) const { if (m_enabled) { @@ -67,7 +67,7 @@ void StructuredLogger::logStarting(string const& _clientImpl, const char* _ethVe } } -void StructuredLogger::logStopping(string const& _clientImpl, const char* _ethVersion) const +void StructuredLogger::stopping(string const& _clientImpl, const char* _ethVersion) const { if (m_enabled) { @@ -80,7 +80,7 @@ void StructuredLogger::logStopping(string const& _clientImpl, const char* _ethVe } } -void StructuredLogger::logP2PConnected(string const& _id, bi::tcp::endpoint const& _addr, +void StructuredLogger::p2pConnected(string const& _id, bi::tcp::endpoint const& _addr, chrono::system_clock::time_point const& _ts, string const& _remoteVersion, unsigned int _numConnections) const { if (m_enabled) @@ -98,7 +98,7 @@ void StructuredLogger::logP2PConnected(string const& _id, bi::tcp::endpoint cons } } -void StructuredLogger::logP2PDisconnected(string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections) const +void StructuredLogger::p2pDisconnected(string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections) const { if (m_enabled) { @@ -114,7 +114,7 @@ void StructuredLogger::logP2PDisconnected(string const& _id, bi::tcp::endpoint c } } -void StructuredLogger::logMinedNewBlock(string const& _hash, string const& _blockNumber, +void StructuredLogger::minedNewBlock(string const& _hash, string const& _blockNumber, string const& _chainHeadHash, string const& _prevHash) const { if (m_enabled) @@ -130,7 +130,7 @@ void StructuredLogger::logMinedNewBlock(string const& _hash, string const& _bloc } } -void StructuredLogger::logChainReceivedNewBlock(string const& _hash, string const& _blockNumber, +void StructuredLogger::chainReceivedNewBlock(string const& _hash, string const& _blockNumber, string const& _chainHeadHash, string const& _remoteID, string const& _prevHash) const { if (m_enabled) @@ -147,7 +147,7 @@ void StructuredLogger::logChainReceivedNewBlock(string const& _hash, string cons } } -void StructuredLogger::logChainNewHead(string const& _hash, string const& _blockNumber, +void StructuredLogger::chainNewHead(string const& _hash, string const& _blockNumber, string const& _chainHeadHash, string const& _prevHash) const { if (m_enabled) @@ -163,7 +163,7 @@ void StructuredLogger::logChainNewHead(string const& _hash, string const& _block } } -void StructuredLogger::logTransactionReceived(string const& _hash, string const& _remoteId) const +void StructuredLogger::transactionReceived(string const& _hash, string const& _remoteId) const { if (m_enabled) { diff --git a/libdevcore/StructuredLogger.h b/libdevcore/StructuredLogger.h index 7fbde7c5a..3557d6c68 100644 --- a/libdevcore/StructuredLogger.h +++ b/libdevcore/StructuredLogger.h @@ -38,31 +38,42 @@ namespace dev class StructuredLogger { public: - /// Default constructor, logging off - StructuredLogger(): m_enabled(false){} /** - * Initializes a structured logger object + * Initializes the structured logger object * @param _enabled Whether logging is on or off * @param _timeFormat A time format string as described here: * http://en.cppreference.com/w/cpp/chrono/c/strftime * with which to display timestamps */ - StructuredLogger(bool _enabled, std::string const& _timeFormat): - m_enabled(_enabled), m_timeFormat(_timeFormat) {} + void initialize(bool _enabled, std::string const& _timeFormat) + { + m_enabled = _enabled; + m_timeFormat = _timeFormat; + } - void logStarting(std::string const& _clientImpl, const char* _ethVersion) const; - void logStopping(std::string const& _clientImpl, const char* _ethVersion) const; - void logP2PConnected(std::string const& _id, bi::tcp::endpoint const& _addr, + static StructuredLogger& get() + { + static StructuredLogger instance; + return instance; + } + + void starting(std::string const& _clientImpl, const char* _ethVersion) const; + void stopping(std::string const& _clientImpl, const char* _ethVersion) const; + void p2pConnected(std::string const& _id, bi::tcp::endpoint const& _addr, std::chrono::system_clock::time_point const& _ts, std::string const& _remoteVersion, unsigned int _numConnections) const; - void logP2PDisconnected(std::string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections) const; - void logMinedNewBlock(std::string const& _hash, std::string const& _blockNumber, + void p2pDisconnected(std::string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections) const; + void minedNewBlock(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, std::string const& _prevHash) const; - void logChainReceivedNewBlock(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, + void chainReceivedNewBlock(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, std::string const& _remoteID, std::string const& _prevHash) const; - void logChainNewHead(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, + void chainNewHead(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, std::string const& _prevHash) const; - void logTransactionReceived(std::string const& _hash, std::string const& _remoteId) const; + void transactionReceived(std::string const& _hash, std::string const& _remoteId) const; private: + // Singleton class, no copying + StructuredLogger() {} + StructuredLogger(StructuredLogger const&) = delete; + void operator=(StructuredLogger const&) = delete; /// @returns a string representation of a timepoint std::string timePointToString(std::chrono::system_clock::time_point const& _ts) const; void outputJson(Json::Value const& _value, std::string const& _name) const; @@ -71,4 +82,8 @@ private: std::string m_timeFormat = "%Y-%m-%dT%H:%M:%S"; }; +/// Convenience macro to get the singleton instance +/// Calling the logging functions becomes as simple as: StructLog.transactionReceived(...) +#define StructLog StructuredLogger::get() + } diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 6cce7b51b..690a8976b 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -152,7 +153,7 @@ inline string toString(h256s const& _bs) return out.str(); } -h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max, StructuredLogger const& _logger) +h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max) { _bq.tick(*this); @@ -164,7 +165,7 @@ h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max { try { - for (auto h: import(block, _stateDB, _logger)) + for (auto h: import(block, _stateDB)) if (!_max--) break; else @@ -187,11 +188,11 @@ h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max return ret; } -h256s BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, StructuredLogger const& _logger) noexcept +h256s BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB) noexcept { try { - return import(_block, _stateDB, _logger); + return import(_block, _stateDB); } catch (...) { @@ -200,7 +201,7 @@ h256s BlockChain::attemptImport(bytes const& _block, OverlayDB const& _stateDB, } } -h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, StructuredLogger const& _logger) +h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) { // VERIFY: populates from the block and checks the block is internally coherent. BlockInfo bi; @@ -317,7 +318,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, StructuredLo } #endif - _logger.logChainReceivedNewBlock( + StructLog.chainReceivedNewBlock( bi.headerHash(WithoutNonce).abridged(), bi.nonce.abridged(), currentHash().abridged(), @@ -337,7 +338,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db, StructuredLo } m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&newHash, 32)); clog(BlockChainNote) << " Imported and best" << td << ". Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(ret); - _logger.logChainNewHead( + StructLog.chainNewHead( bi.headerHash(WithoutNonce).abridged(), bi.nonce.abridged(), currentHash().abridged(), diff --git a/libethereum/BlockChain.h b/libethereum/BlockChain.h index 6d36b14cd..576deaadf 100644 --- a/libethereum/BlockChain.h +++ b/libethereum/BlockChain.h @@ -32,7 +32,6 @@ #include #include #include -#include #include "BlockDetails.h" #include "Account.h" #include "BlockQueue.h" @@ -80,15 +79,15 @@ public: void process(); /// Sync the chain with any incoming blocks. All blocks should, if processed in order - h256s sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max, StructuredLogger const& _logger); + h256s sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max); /// Attempt to import the given block directly into the CanonBlockChain and sync with the state DB. /// @returns the block hashes of any blocks that came into/went out of the canonical block chain. - h256s attemptImport(bytes const& _block, OverlayDB const& _stateDB, StructuredLogger const& _logger = StructuredLogger()) noexcept; + h256s attemptImport(bytes const& _block, OverlayDB const& _stateDB) noexcept; /// Import block into disk-backed DB /// @returns the block hashes of any blocks that came into/went out of the canonical block chain. - h256s import(bytes const& _block, OverlayDB const& _stateDB, StructuredLogger const& _logger = StructuredLogger()); + h256s import(bytes const& _block, OverlayDB const& _stateDB); /// Returns true if the given block is known (though not necessarily a part of the canon chain). bool isKnown(h256 _hash) const; diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index a4e9c9a66..38901643a 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "Defaults.h" #include "Executive.h" @@ -59,15 +60,13 @@ void VersionChecker::setOk() } } -Client::Client(p2p::Host* _extNet, std::string const& _dbPath, bool _forceClean, - u256 _networkId, int _miners, StructuredLogger const& _structuredLogger): +Client::Client(p2p::Host* _extNet, std::string const& _dbPath, bool _forceClean, u256 _networkId, int _miners): Worker("eth"), m_vc(_dbPath), m_bc(_dbPath, !m_vc.ok() || _forceClean), m_stateDB(State::openDB(_dbPath, !m_vc.ok() || _forceClean)), m_preMine(Address(), m_stateDB), - m_postMine(Address(), m_stateDB), - m_structuredLogger(_structuredLogger) + m_postMine(Address(), m_stateDB) { m_host = _extNet->registerCapability(new EthereumHost(m_bc, m_tq, m_bq, _networkId)); @@ -417,7 +416,7 @@ void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _ } Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); // cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); - m_structuredLogger.logTransactionReceived(t.sha3().abridged(), t.sender().abridged()); + StructLog.transactionReceived(t.sha3().abridged(), t.sender().abridged()); cnote << "New transaction " << t; m_tq.attemptImport(t.rlp()); } @@ -523,7 +522,7 @@ void Client::doWork() h256s hs; { WriteGuard l(x_stateDB); - hs = m_bc.attemptImport(m.blockData(), m_stateDB, m_structuredLogger); + hs = m_bc.attemptImport(m.blockData(), m_stateDB); } if (hs.size()) { @@ -558,7 +557,7 @@ void Client::doWork() cwork << "BQ ==> CHAIN ==> STATE"; OverlayDB db = m_stateDB; x_stateDB.unlock(); - h256s newBlocks = m_bc.sync(m_bq, db, 100, m_structuredLogger); // TODO: remove transactions from m_tq nicely rather than relying on out of date nonce later on. + h256s newBlocks = m_bc.sync(m_bq, db, 100); // TODO: remove transactions from m_tq nicely rather than relying on out of date nonce later on. if (newBlocks.size()) { for (auto i: newBlocks) diff --git a/libethereum/Client.h b/libethereum/Client.h index 33b0080f2..31aa1aee3 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include "CanonBlockChain.h" @@ -169,7 +168,7 @@ class Client: public MinerHost, public Interface, Worker public: /// New-style Constructor. explicit Client(p2p::Host* _host, std::string const& _dbPath = std::string(), bool _forceClean = false, - u256 _networkId = 0, int _miners = -1, StructuredLogger const& _structuredLogger = StructuredLogger()); + u256 _networkId = 0, int _miners = -1); /// Destructor. virtual ~Client(); @@ -367,7 +366,6 @@ private: std::map m_filters; std::map m_watches; - StructuredLogger const& m_structuredLogger; mutable std::chrono::system_clock::time_point m_lastGarbageCollection; }; diff --git a/libethereum/Miner.cpp b/libethereum/Miner.cpp index 03cceed74..a049fca2f 100644 --- a/libethereum/Miner.cpp +++ b/libethereum/Miner.cpp @@ -36,10 +36,9 @@ LocalMiner::LocalMiner(MinerHost* _host, unsigned _id): { } -void LocalMiner::setup(MinerHost* _host, unsigned _id, StructuredLogger const* _structuredLogger) +void LocalMiner::setup(MinerHost* _host, unsigned _id) { m_host = _host; - m_structuredLogger = _structuredLogger; setName("miner-" + toString(_id)); } @@ -80,7 +79,7 @@ void LocalMiner::doWork() } if (mineInfo.completed) { - m_mineState.completeMine(m_structuredLogger); + m_mineState.completeMine(); m_host->onComplete(); m_miningStatus = Mined; } diff --git a/libethereum/Miner.h b/libethereum/Miner.h index c8f9691f4..5914770d2 100644 --- a/libethereum/Miner.h +++ b/libethereum/Miner.h @@ -33,7 +33,6 @@ namespace dev { -class StructuredLogger; namespace eth { @@ -106,7 +105,7 @@ public: ~LocalMiner() { stop(); } /// Setup its basics. - void setup(MinerHost* _host, unsigned _id = 0, StructuredLogger const* _structuredLogger = nullptr); + void setup(MinerHost* _host, unsigned _id = 0); /// Start mining. void start() { startWorking(); } @@ -145,7 +144,6 @@ private: mutable std::mutex x_mineInfo; ///< Lock for the mining progress & history. MineProgress m_mineProgress; ///< What's our progress? std::list m_mineHistory; ///< What the history of our mining? - StructuredLogger const* m_structuredLogger; }; } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index edaa3a6dc..0fd94175c 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -802,12 +802,12 @@ bool State::completeMine(h256 const& _nonce) m_currentBlock.nonce = _nonce; cnote << "Completed" << m_currentBlock.headerHash(WithoutNonce).abridged() << m_currentBlock.nonce.abridged() << m_currentBlock.difficulty << ProofOfWork::verify(m_currentBlock.headerHash(WithoutNonce), m_currentBlock.nonce, m_currentBlock.difficulty); - completeMine(nullptr); + completeMine(); return true; } -void State::completeMine(StructuredLogger const* _structuredLogger) +void State::completeMine() { cdebug << "Completing mine!"; // Got it! @@ -821,13 +821,12 @@ void State::completeMine(StructuredLogger const* _structuredLogger) ret.swapOut(m_currentBytes); m_currentBlock.hash = sha3(RLP(m_currentBytes)[0].data()); cnote << "Mined " << m_currentBlock.hash.abridged() << "(parent: " << m_currentBlock.parentHash.abridged() << ")"; - if (_structuredLogger) - _structuredLogger->logMinedNewBlock( - m_currentBlock.hash.abridged(), - m_currentBlock.nonce.abridged(), - "", //TODO: chain head hash here ?? - m_currentBlock.parentHash.abridged() - ); + StructLog.minedNewBlock( + m_currentBlock.hash.abridged(), + m_currentBlock.nonce.abridged(), + "", //TODO: chain head hash here ?? + m_currentBlock.parentHash.abridged() + ); // Quickly reset the transactions. // TODO: Leave this in a better state than this limbo, or at least record that it's in limbo. diff --git a/libethereum/State.h b/libethereum/State.h index cd1048d60..813141d17 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -41,8 +41,6 @@ namespace dev { -class StructuredLogger; - namespace test { class ImportTest; } namespace eth @@ -141,7 +139,7 @@ public: * // unlock * @endcode */ - void completeMine(StructuredLogger const* _structuredLogger = nullptr); + void completeMine(); /// Get the complete current block, including valid nonce. /// Only valid after mine() returns true. diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index ffc726db8..aa8b64f3c 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include "Session.h" @@ -45,7 +46,7 @@ void HostNodeTableHandler::processEvent(NodeId const& _n, NodeTableEventType con m_host.onNodeTableEvent(_n, _e); } -Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bytesConstRef _restoreNetwork, StructuredLogger const& _structuredLogger): +Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, bytesConstRef _restoreNetwork): Worker("p2p", 0), m_restoreNetwork(_restoreNetwork.toBytes()), m_clientVersion(_clientVersion), @@ -54,8 +55,7 @@ Host::Host(std::string const& _clientVersion, NetworkPreferences const& _n, byte m_ioService(2), m_tcp4Acceptor(m_ioService), m_alias(networkAlias(_restoreNetwork)), - m_lastPing(chrono::steady_clock::time_point::min()), - m_structuredLogger(_structuredLogger) + m_lastPing(chrono::steady_clock::time_point::min()) { for (auto address: m_ifAddresses) if (address.is_v4()) @@ -159,7 +159,7 @@ void Host::registerPeer(std::shared_ptr _s, CapDescs const& _caps) { { clog(NetNote) << "p2p.host.peer.register" << _s->m_peer->id.abridged(); - m_structuredLogger.logP2PConnected( + StructLog.p2pConnected( _s->m_peer->id.abridged(), _s->m_peer->peerEndpoint(), _s->m_peer->m_lastConnected, _s->m_info.clientVersion, diff --git a/libp2p/Host.h b/libp2p/Host.h index de984ca59..6f5c5a50c 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -33,7 +33,6 @@ #include #include #include -#include #include #include "NodeTable.h" #include "HostCapability.h" @@ -87,7 +86,7 @@ class Host: public Worker public: /// Start server, listening for connections on the given port. Host(std::string const& _clientVersion, NetworkPreferences const& _n = NetworkPreferences(), - bytesConstRef _restoreNetwork = bytesConstRef(), StructuredLogger const& _structuredLogger = StructuredLogger()); + bytesConstRef _restoreNetwork = bytesConstRef()); /// Will block on network process events. virtual ~Host(); @@ -234,7 +233,6 @@ private: std::map> m_capabilities; ///< Each of the capabilities we support. std::chrono::steady_clock::time_point m_lastPing; ///< Time we sent the last ping to all peers. - StructuredLogger const& m_structuredLogger; bool m_accepting = false; }; diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp index 78caa6273..9817cb5f9 100644 --- a/libp2p/Session.cpp +++ b/libp2p/Session.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "Host.h" #include "Capability.h" @@ -467,8 +468,10 @@ void Session::drop(DisconnectReason _reason) void Session::disconnect(DisconnectReason _reason) { clogS(NetConnect) << "Disconnecting (our reason:" << reasonOf(_reason) << ")"; - m_server->m_structuredLogger.logP2PDisconnected(m_info.id.abridged(), m_peer->peerEndpoint(), - 0);// TODO: num connections + StructLog.p2pDisconnected( + m_info.id.abridged(), + m_peer->peerEndpoint(), + 0);// TODO: num connections if (m_socket.is_open()) { RLPStream s; diff --git a/libwebthree/WebThree.cpp b/libwebthree/WebThree.cpp index 50e988932..c97e4b5c8 100644 --- a/libwebthree/WebThree.cpp +++ b/libwebthree/WebThree.cpp @@ -37,14 +37,14 @@ using namespace dev::shh; WebThreeDirect::WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean, std::set const& _interfaces, NetworkPreferences const& _n, - bytesConstRef _network, int _miners, StructuredLogger const& _structuredLogger): + bytesConstRef _network, int _miners): m_clientVersion(_clientVersion), - m_net(_clientVersion, _n, _network, _structuredLogger) + m_net(_clientVersion, _n, _network) { if (_dbPath.size()) Defaults::setDBPath(_dbPath); if (_interfaces.count("eth")) - m_ethereum.reset(new eth::Client(&m_net, _dbPath, _forceClean, 0, _miners, _structuredLogger)); + m_ethereum.reset(new eth::Client(&m_net, _dbPath, _forceClean, 0, _miners)); if (_interfaces.count("shh")) m_whisper = m_net.registerCapability(new WhisperHost); diff --git a/libwebthree/WebThree.h b/libwebthree/WebThree.h index 197181335..9eb9111b4 100644 --- a/libwebthree/WebThree.h +++ b/libwebthree/WebThree.h @@ -106,7 +106,7 @@ public: WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean = false, std::set const& _interfaces = {"eth", "shh"}, p2p::NetworkPreferences const& _n = p2p::NetworkPreferences(), - bytesConstRef _network = bytesConstRef(), int _miners = -1, StructuredLogger const& _structuredLogger = StructuredLogger()); + bytesConstRef _network = bytesConstRef(), int _miners = -1); /// Destructor. ~WebThreeDirect(); From 0fba1cc063bbc481fa5cd46f9c5808121703c9aa Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 2 Mar 2015 14:02:57 +0100 Subject: [PATCH 23/54] Adding number of connections in the p2p events --- libp2p/Host.cpp | 5 +++-- libp2p/Session.cpp | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index aa8b64f3c..5bee1dbc9 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -160,10 +160,11 @@ void Host::registerPeer(std::shared_ptr _s, CapDescs const& _caps) { clog(NetNote) << "p2p.host.peer.register" << _s->m_peer->id.abridged(); StructLog.p2pConnected( - _s->m_peer->id.abridged(), _s->m_peer->peerEndpoint(), + _s->m_peer->id.abridged(), + _s->m_peer->peerEndpoint(), _s->m_peer->m_lastConnected, _s->m_info.clientVersion, - 0);// TODO: num_connections + peerCount()); RecursiveGuard l(x_sessions); // TODO: temporary loose-coupling; if m_peers already has peer, // it is same as _s->m_peer. (fixing next PR) diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp index 9817cb5f9..ffd2dbc90 100644 --- a/libp2p/Session.cpp +++ b/libp2p/Session.cpp @@ -471,7 +471,8 @@ void Session::disconnect(DisconnectReason _reason) StructLog.p2pDisconnected( m_info.id.abridged(), m_peer->peerEndpoint(), - 0);// TODO: num connections + m_server->peerCount() + ); if (m_socket.is_open()) { RLPStream s; From ae6510b135a632ac2c3cbcac6245464e670ad8bb Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 2 Mar 2015 17:04:04 +0100 Subject: [PATCH 24/54] Style fixes --- libdevcore/StructuredLogger.cpp | 26 ++++++++++++++++++-------- libdevcore/StructuredLogger.h | 24 +++++++++++++++++------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/libdevcore/StructuredLogger.cpp b/libdevcore/StructuredLogger.cpp index 5fd605e3a..2e8b279d1 100644 --- a/libdevcore/StructuredLogger.cpp +++ b/libdevcore/StructuredLogger.cpp @@ -80,8 +80,11 @@ void StructuredLogger::stopping(string const& _clientImpl, const char* _ethVersi } } -void StructuredLogger::p2pConnected(string const& _id, bi::tcp::endpoint const& _addr, - chrono::system_clock::time_point const& _ts, string const& _remoteVersion, unsigned int _numConnections) const +void StructuredLogger::p2pConnected(string const& _id, + bi::tcp::endpoint const& _addr, + chrono::system_clock::time_point const& _ts, + string const& _remoteVersion, + unsigned int _numConnections) const { if (m_enabled) { @@ -114,8 +117,10 @@ void StructuredLogger::p2pDisconnected(string const& _id, bi::tcp::endpoint cons } } -void StructuredLogger::minedNewBlock(string const& _hash, string const& _blockNumber, - string const& _chainHeadHash, string const& _prevHash) const +void StructuredLogger::minedNewBlock(string const& _hash, + string const& _blockNumber, + string const& _chainHeadHash, + string const& _prevHash) const { if (m_enabled) { @@ -130,8 +135,11 @@ void StructuredLogger::minedNewBlock(string const& _hash, string const& _blockNu } } -void StructuredLogger::chainReceivedNewBlock(string const& _hash, string const& _blockNumber, - string const& _chainHeadHash, string const& _remoteID, string const& _prevHash) const +void StructuredLogger::chainReceivedNewBlock(string const& _hash, + string const& _blockNumber, + string const& _chainHeadHash, + string const& _remoteID, + string const& _prevHash) const { if (m_enabled) { @@ -147,8 +155,10 @@ void StructuredLogger::chainReceivedNewBlock(string const& _hash, string const& } } -void StructuredLogger::chainNewHead(string const& _hash, string const& _blockNumber, - string const& _chainHeadHash, string const& _prevHash) const +void StructuredLogger::chainNewHead(string const& _hash, + string const& _blockNumber, + string const& _chainHeadHash, + string const& _prevHash) const { if (m_enabled) { diff --git a/libdevcore/StructuredLogger.h b/libdevcore/StructuredLogger.h index 3557d6c68..ebceecdff 100644 --- a/libdevcore/StructuredLogger.h +++ b/libdevcore/StructuredLogger.h @@ -59,14 +59,24 @@ public: void starting(std::string const& _clientImpl, const char* _ethVersion) const; void stopping(std::string const& _clientImpl, const char* _ethVersion) const; - void p2pConnected(std::string const& _id, bi::tcp::endpoint const& _addr, - std::chrono::system_clock::time_point const& _ts, std::string const& _remoteVersion, unsigned int _numConnections) const; + void p2pConnected(std::string const& _id, + bi::tcp::endpoint const& _addr, + std::chrono::system_clock::time_point const& _ts, + std::string const& _remoteVersion, + unsigned int _numConnections) const; void p2pDisconnected(std::string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections) const; - void minedNewBlock(std::string const& _hash, std::string const& _blockNumber, - std::string const& _chainHeadHash, std::string const& _prevHash) const; - void chainReceivedNewBlock(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, - std::string const& _remoteID, std::string const& _prevHash) const; - void chainNewHead(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, + void minedNewBlock(std::string const& _hash, + std::string const& _blockNumber, + std::string const& _chainHeadHash, + std::string const& _prevHash) const; + void chainReceivedNewBlock(std::string const& _hash, + std::string const& _blockNumber, + std::string const& _chainHeadHash, + std::string const& _remoteID, + std::string const& _prevHash) const; + void chainNewHead(std::string const& _hash, + std::string const& _blockNumber, + std::string const& _chainHeadHash, std::string const& _prevHash) const; void transactionReceived(std::string const& _hash, std::string const& _remoteId) const; private: From 4a9b2fa0c5b10f16c0a284c4e8bd4cc67fd91193 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Mon, 2 Mar 2015 17:25:01 +0100 Subject: [PATCH 25/54] StructuredLogger's functions all become static and call the singleton getter. --- eth/main.cpp | 6 ++-- libdevcore/StructuredLogger.cpp | 52 ++++++++++++++++----------------- libdevcore/StructuredLogger.h | 30 +++++++++---------- libethereum/BlockChain.cpp | 4 +-- libethereum/Client.cpp | 2 +- libethereum/State.cpp | 2 +- libp2p/Host.cpp | 2 +- libp2p/Session.cpp | 2 +- 8 files changed, 48 insertions(+), 52 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index fa78a4190..8014cc0fa 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -359,7 +359,7 @@ int main(int argc, char** argv) cout << credits(); - StructLog.initialize(structuredLogging, structuredLoggingFormat); + StructuredLogger::get().initialize(structuredLogging, structuredLoggingFormat); VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter); NetworkPreferences netPrefs(listenPort, publicIP, upnp, useLocal); auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp"); @@ -375,7 +375,7 @@ int main(int argc, char** argv) ); web3.setIdealPeerCount(peers); eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr; - StructLog.starting(clientImplString, dev::Version); + StructuredLogger::starting(clientImplString, dev::Version); if (c) { c->setForceMining(forceMining); @@ -909,7 +909,7 @@ int main(int argc, char** argv) while (!g_exit) this_thread::sleep_for(chrono::milliseconds(1000)); - StructLog.stopping(clientImplString, dev::Version); + StructuredLogger::stopping(clientImplString, dev::Version); auto netData = web3.saveNetwork(); if (!netData.empty()) writeFile((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp", netData); diff --git a/libdevcore/StructuredLogger.cpp b/libdevcore/StructuredLogger.cpp index 2e8b279d1..cb6acd501 100644 --- a/libdevcore/StructuredLogger.cpp +++ b/libdevcore/StructuredLogger.cpp @@ -32,7 +32,7 @@ using namespace std; namespace dev { -string StructuredLogger::timePointToString(chrono::system_clock::time_point const& _ts) const +string StructuredLogger::timePointToString(chrono::system_clock::time_point const& _ts) { // not using C++11 std::put_time due to gcc bug // http://stackoverflow.com/questions/14136833/stdput-time-implementation-status-in-gcc @@ -40,7 +40,7 @@ string StructuredLogger::timePointToString(chrono::system_clock::time_point cons char buffer[64]; time_t time = chrono::system_clock::to_time_t(_ts); tm* ptm = localtime(&time); - if (strftime(buffer, sizeof(buffer), m_timeFormat.c_str(), ptm)) + if (strftime(buffer, sizeof(buffer), get().m_timeFormat.c_str(), ptm)) return string(buffer); return ""; } @@ -54,29 +54,29 @@ void StructuredLogger::outputJson(Json::Value const& _value, std::string const& cout << event << endl << flush; } -void StructuredLogger::starting(string const& _clientImpl, const char* _ethVersion) const +void StructuredLogger::starting(string const& _clientImpl, const char* _ethVersion) { - if (m_enabled) + if (get().m_enabled) { Json::Value event; event["client_impl"] = _clientImpl; event["eth_version"] = std::string(_ethVersion); event["ts"] = timePointToString(std::chrono::system_clock::now()); - outputJson(event, "starting"); + get().outputJson(event, "starting"); } } -void StructuredLogger::stopping(string const& _clientImpl, const char* _ethVersion) const +void StructuredLogger::stopping(string const& _clientImpl, const char* _ethVersion) { - if (m_enabled) + if (get().m_enabled) { Json::Value event; event["client_impl"] = _clientImpl; event["eth_version"] = std::string(_ethVersion); event["ts"] = timePointToString(std::chrono::system_clock::now()); - outputJson(event, "stopping"); + get().outputJson(event, "stopping"); } } @@ -84,9 +84,9 @@ void StructuredLogger::p2pConnected(string const& _id, bi::tcp::endpoint const& _addr, chrono::system_clock::time_point const& _ts, string const& _remoteVersion, - unsigned int _numConnections) const + unsigned int _numConnections) { - if (m_enabled) + if (get().m_enabled) { std::stringstream addrStream; addrStream << _addr; @@ -97,13 +97,13 @@ void StructuredLogger::p2pConnected(string const& _id, event["num_connections"] = Json::Value(_numConnections); event["ts"] = timePointToString(_ts); - outputJson(event, "p2p.connected"); + get().outputJson(event, "p2p.connected"); } } -void StructuredLogger::p2pDisconnected(string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections) const +void StructuredLogger::p2pDisconnected(string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections) { - if (m_enabled) + if (get().m_enabled) { std::stringstream addrStream; addrStream << _addr; @@ -113,16 +113,16 @@ void StructuredLogger::p2pDisconnected(string const& _id, bi::tcp::endpoint cons event["num_connections"] = Json::Value(_numConnections); event["ts"] = timePointToString(chrono::system_clock::now()); - outputJson(event, "p2p.disconnected"); + get().outputJson(event, "p2p.disconnected"); } } void StructuredLogger::minedNewBlock(string const& _hash, string const& _blockNumber, string const& _chainHeadHash, - string const& _prevHash) const + string const& _prevHash) { - if (m_enabled) + if (get().m_enabled) { Json::Value event; event["block_hash"] = _hash; @@ -131,7 +131,7 @@ void StructuredLogger::minedNewBlock(string const& _hash, event["ts"] = timePointToString(std::chrono::system_clock::now()); event["block_prev_hash"] = _prevHash; - outputJson(event, "eth.miner.new_block"); + get().outputJson(event, "eth.miner.new_block"); } } @@ -139,9 +139,9 @@ void StructuredLogger::chainReceivedNewBlock(string const& _hash, string const& _blockNumber, string const& _chainHeadHash, string const& _remoteID, - string const& _prevHash) const + string const& _prevHash) { - if (m_enabled) + if (get().m_enabled) { Json::Value event; event["block_hash"] = _hash; @@ -151,16 +151,16 @@ void StructuredLogger::chainReceivedNewBlock(string const& _hash, event["ts"] = timePointToString(chrono::system_clock::now()); event["block_prev_hash"] = _prevHash; - outputJson(event, "eth.chain.received.new_block"); + get().outputJson(event, "eth.chain.received.new_block"); } } void StructuredLogger::chainNewHead(string const& _hash, string const& _blockNumber, string const& _chainHeadHash, - string const& _prevHash) const + string const& _prevHash) { - if (m_enabled) + if (get().m_enabled) { Json::Value event; event["block_hash"] = _hash; @@ -169,20 +169,20 @@ void StructuredLogger::chainNewHead(string const& _hash, event["ts"] = timePointToString(chrono::system_clock::now()); event["block_prev_hash"] = _prevHash; - outputJson(event, "eth.miner.new_block"); + get().outputJson(event, "eth.miner.new_block"); } } -void StructuredLogger::transactionReceived(string const& _hash, string const& _remoteId) const +void StructuredLogger::transactionReceived(string const& _hash, string const& _remoteId) { - if (m_enabled) + if (get().m_enabled) { Json::Value event; event["tx_hash"] = _hash; event["remote_id"] = _remoteId; event["ts"] = timePointToString(chrono::system_clock::now()); - outputJson(event, "eth.tx.received"); + get().outputJson(event, "eth.tx.received"); } } diff --git a/libdevcore/StructuredLogger.h b/libdevcore/StructuredLogger.h index ebceecdff..522a5115d 100644 --- a/libdevcore/StructuredLogger.h +++ b/libdevcore/StructuredLogger.h @@ -57,43 +57,39 @@ public: return instance; } - void starting(std::string const& _clientImpl, const char* _ethVersion) const; - void stopping(std::string const& _clientImpl, const char* _ethVersion) const; - void p2pConnected(std::string const& _id, + static void starting(std::string const& _clientImpl, const char* _ethVersion); + static void stopping(std::string const& _clientImpl, const char* _ethVersion); + static void p2pConnected(std::string const& _id, bi::tcp::endpoint const& _addr, std::chrono::system_clock::time_point const& _ts, std::string const& _remoteVersion, - unsigned int _numConnections) const; - void p2pDisconnected(std::string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections) const; - void minedNewBlock(std::string const& _hash, + unsigned int _numConnections); + static void p2pDisconnected(std::string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections); + static void minedNewBlock(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, - std::string const& _prevHash) const; - void chainReceivedNewBlock(std::string const& _hash, + std::string const& _prevHash); + static void chainReceivedNewBlock(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, std::string const& _remoteID, - std::string const& _prevHash) const; - void chainNewHead(std::string const& _hash, + std::string const& _prevHash); + static void chainNewHead(std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, - std::string const& _prevHash) const; - void transactionReceived(std::string const& _hash, std::string const& _remoteId) const; + std::string const& _prevHash); + static void transactionReceived(std::string const& _hash, std::string const& _remoteId); private: // Singleton class, no copying StructuredLogger() {} StructuredLogger(StructuredLogger const&) = delete; void operator=(StructuredLogger const&) = delete; /// @returns a string representation of a timepoint - std::string timePointToString(std::chrono::system_clock::time_point const& _ts) const; + static std::string timePointToString(std::chrono::system_clock::time_point const& _ts); void outputJson(Json::Value const& _value, std::string const& _name) const; bool m_enabled; std::string m_timeFormat = "%Y-%m-%dT%H:%M:%S"; }; -/// Convenience macro to get the singleton instance -/// Calling the logging functions becomes as simple as: StructLog.transactionReceived(...) -#define StructLog StructuredLogger::get() - } diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 690a8976b..784621a69 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -318,7 +318,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) } #endif - StructLog.chainReceivedNewBlock( + StructuredLogger::chainReceivedNewBlock( bi.headerHash(WithoutNonce).abridged(), bi.nonce.abridged(), currentHash().abridged(), @@ -338,7 +338,7 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) } m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&newHash, 32)); clog(BlockChainNote) << " Imported and best" << td << ". Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(ret); - StructLog.chainNewHead( + StructuredLogger::chainNewHead( bi.headerHash(WithoutNonce).abridged(), bi.nonce.abridged(), currentHash().abridged(), diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 38901643a..910f3650e 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -416,7 +416,7 @@ void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _ } Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); // cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); - StructLog.transactionReceived(t.sha3().abridged(), t.sender().abridged()); + StructuredLogger::transactionReceived(t.sha3().abridged(), t.sender().abridged()); cnote << "New transaction " << t; m_tq.attemptImport(t.rlp()); } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 0fd94175c..fad9112db 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -821,7 +821,7 @@ void State::completeMine() ret.swapOut(m_currentBytes); m_currentBlock.hash = sha3(RLP(m_currentBytes)[0].data()); cnote << "Mined " << m_currentBlock.hash.abridged() << "(parent: " << m_currentBlock.parentHash.abridged() << ")"; - StructLog.minedNewBlock( + StructuredLogger::minedNewBlock( m_currentBlock.hash.abridged(), m_currentBlock.nonce.abridged(), "", //TODO: chain head hash here ?? diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 5bee1dbc9..bb97f06e4 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -159,7 +159,7 @@ void Host::registerPeer(std::shared_ptr _s, CapDescs const& _caps) { { clog(NetNote) << "p2p.host.peer.register" << _s->m_peer->id.abridged(); - StructLog.p2pConnected( + StructuredLogger::p2pConnected( _s->m_peer->id.abridged(), _s->m_peer->peerEndpoint(), _s->m_peer->m_lastConnected, diff --git a/libp2p/Session.cpp b/libp2p/Session.cpp index ffd2dbc90..ec0a2d0d7 100644 --- a/libp2p/Session.cpp +++ b/libp2p/Session.cpp @@ -468,7 +468,7 @@ void Session::drop(DisconnectReason _reason) void Session::disconnect(DisconnectReason _reason) { clogS(NetConnect) << "Disconnecting (our reason:" << reasonOf(_reason) << ")"; - StructLog.p2pDisconnected( + StructuredLogger::p2pDisconnected( m_info.id.abridged(), m_peer->peerEndpoint(), m_server->peerCount() From aabce8548a4eb908cc55ff4c5509b8ddc9f97ec3 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 3 Mar 2015 00:27:05 +0100 Subject: [PATCH 26/54] mini style improvement --- libdevcore/StructuredLogger.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libdevcore/StructuredLogger.h b/libdevcore/StructuredLogger.h index 522a5115d..288e468f3 100644 --- a/libdevcore/StructuredLogger.h +++ b/libdevcore/StructuredLogger.h @@ -80,15 +80,16 @@ public: std::string const& _prevHash); static void transactionReceived(std::string const& _hash, std::string const& _remoteId); private: - // Singleton class, no copying - StructuredLogger() {} + // Singleton class. Private default ctor and no copying + StructuredLogger() = default; StructuredLogger(StructuredLogger const&) = delete; void operator=(StructuredLogger const&) = delete; + /// @returns a string representation of a timepoint static std::string timePointToString(std::chrono::system_clock::time_point const& _ts); void outputJson(Json::Value const& _value, std::string const& _name) const; - bool m_enabled; + bool m_enabled = false; std::string m_timeFormat = "%Y-%m-%dT%H:%M:%S"; }; From e44ab4588d08449a5c0b6cb8f1a07b7649f0093f Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 3 Mar 2015 13:28:19 +0100 Subject: [PATCH 27/54] fixing the build --- libdevcore/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index d11fa7ea4..a527aa7b0 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -12,6 +12,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) include_directories(BEFORE ..) include_directories(${Boost_INCLUDE_DIRS}) From 148e2d8d14bac845bf2eaf4e3cb25610183df2d1 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 3 Mar 2015 15:56:49 +0100 Subject: [PATCH 28/54] fixing pr issues --- libethereum/Client.cpp | 4 ++-- libevm/ExtVMFace.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 02412f4c1..fe07cbb18 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -794,7 +794,7 @@ LocalisedLogEntries Client::logs(LogFilter const& _f) const TransactionReceipt receipt = receipts[i]; if (_f.matches(receipt.bloom())) { - auto sha3 = transaction(info.hash, i).sha3(); + auto h = transaction(info.hash, i).sha3(); LogEntries le = _f.matches(receipt); if (le.size()) { @@ -806,7 +806,7 @@ LocalisedLogEntries Client::logs(LogFilter const& _f) const if (s) s--; else - ret.insert(ret.begin(), LocalisedLogEntry(le[j], n, sha3)); + ret.insert(ret.begin(), LocalisedLogEntry(le[j], n, h)); } } } diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 95910d7cb..49535958a 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -63,7 +63,7 @@ using LogEntries = std::vector; struct LocalisedLogEntry: public LogEntry { LocalisedLogEntry() {} - LocalisedLogEntry(LogEntry const& _le, unsigned _number, h256 _sha3 = h256(u256(0))): LogEntry(_le), number(_number), sha3(_sha3) {} + LocalisedLogEntry(LogEntry const& _le, unsigned _number, h256 _sha3 = {}): LogEntry(_le), number(_number), sha3(_sha3) {} unsigned number = 0; h256 sha3; From ff644c65c1fb3b0b0c84fc5656d861dded9858a1 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 3 Mar 2015 16:39:10 +0100 Subject: [PATCH 29/54] - The first account use to deploy config contracts. - Other accounts are rdeletable if not used by a transaction. --- mix/ClientModel.cpp | 9 +++----- mix/MixClient.cpp | 5 +++- mix/qml/StateDialog.qml | 47 +++++++++++++++++++++++++++++++++++--- mix/qml/StateListModel.qml | 22 +++++++++++------- 4 files changed, 65 insertions(+), 18 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 9eaab7ed3..ab7b5c7ea 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -48,8 +48,6 @@ namespace dev namespace mix { -const Secret c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); - class RpcConnector: public jsonrpc::AbstractServerConnector { public: @@ -159,7 +157,6 @@ void ClientModel::setupState(QVariantMap _state) QVariantList transactions = _state.value("transactions").toList(); std::map accounts; - accounts.insert(std::make_pair(c_defaultUserAccountSecret, 10000 * ether)); //Default account, used to deploy config contracts. for (auto const& b: balances) { QVariantMap address = b.toMap(); @@ -175,7 +172,7 @@ void ClientModel::setupState(QVariantMap _state) u256 gas = boost::get(qvariant_cast(transaction.value("gas"))->internalValue()); 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()); if (isStdContract) { @@ -185,7 +182,7 @@ void ClientModel::setupState(QVariantMap _state) transactionSettings.gasPrice = 10000000000000; transactionSettings.gas = 125000; transactionSettings.value = 0; - transactionSettings.sender = c_defaultUserAccountSecret; + transactionSettings.sender = Secret(sender.toStdString()); transactionSequence.push_back(transactionSettings); } else @@ -193,7 +190,7 @@ void ClientModel::setupState(QVariantMap _state) if (contractId.isEmpty() && m_context->codeModel()->hasContract()) //TODO: This is to support old project files, remove later contractId = m_context->codeModel()->contracts().keys()[0]; QVariantList qParams = transaction.value("qType").toList(); - QString sender = transaction.value("sender").toString(); + TransactionSettings transactionSettings(contractId, functionId, value, gas, gasPrice, Secret(sender.toStdString())); for (QVariant const& variant: qParams) diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index a048bbca4..7b38a3743 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -41,6 +41,7 @@ namespace dev namespace mix { +const Secret c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); const u256 c_mixGenesisDifficulty = (u256) 1 << 4; class MixBlockChain: public dev::eth::BlockChain @@ -64,7 +65,9 @@ public: MixClient::MixClient(std::string const& _dbPath): m_dbPath(_dbPath), m_minigThreads(0) { - //resetState(); + std::map account; + account.insert(std::make_pair(c_defaultUserAccountSecret, 1000000 * ether)); + resetState(account); } MixClient::~MixClient() diff --git a/mix/qml/StateDialog.qml b/mix/qml/StateDialog.qml index 6a41043aa..21b441845 100644 --- a/mix/qml/StateDialog.qml +++ b/mix/qml/StateDialog.qml @@ -1,5 +1,6 @@ import QtQuick 2.2 import QtQuick.Controls 1.1 +import QtQuick.Dialogs 1.1 import QtQuick.Layouts 1.1 import QtQuick.Window 2.0 import QtQuick.Controls.Styles 1.3 @@ -12,7 +13,7 @@ Window { id: modalStateDialog modality: Qt.ApplicationModal - width: 570 + width: 590 height: 480 title: qsTr("Edit State") visible: false @@ -129,20 +130,50 @@ Window { } } + MessageDialog + { + id: alertAlreadyUsed + text: qsTr("This account is in use. You cannot remove it. The first account is used to deploy config contract and cannot be removed.") + icon: StandardIcon.Warning + standardButtons: StandardButton.Ok + } + TableView { id: accountsView Layout.fillWidth: true model: accountsModel + headerVisible: false TableViewColumn { role: "name" title: qsTr("Name") - width: 120 + width: 150 delegate: Item { - Rectangle + RowLayout { height: 25 width: parent.width + Button + { + iconSource: "qrc:/qml/img/delete_sign.png" + action: deleteAccountAction + } + + Action { + id: deleteAccountAction + tooltip: qsTr("delete Account") + onTriggered: + { + if (transactionsModel.isUsed(stateAccounts[styleData.row].secret)) + alertAlreadyUsed.open(); + else + { + stateAccounts.splice(styleData.row, 1); + accountsModel.remove(styleData.row); + } + } + } + DefaultTextField { anchors.verticalCenter: parent.verticalCenter onTextChanged: { @@ -304,6 +335,16 @@ Window { stateTransactions.splice(index, 1); transactionsModel.remove(index); } + + function isUsed(secret) + { + for (var i in stateTransactions) + { + if (stateTransactions[i].sender === secret) + return true; + } + return false; + } } Component { diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index 4b83c54d7..c2eb43bc1 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -11,10 +11,10 @@ Item { property alias model: stateListModel property var stateList: [] - + property string defaultAccount: "cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074" function fromPlainStateItem(s) { if (!s.accounts) - s.accounts = [stateListModel.newAccount("1000000", QEther.Ether)]; //support old project + s.accounts = [stateListModel.newAccount("1000000", QEther.Ether, defaultAccount)]; //support old project return { title: s.title, transactions: s.transactions.map(fromPlainTransactionItem), @@ -32,6 +32,8 @@ Item { } function fromPlainTransactionItem(t) { + if (!t.sender) + t.sender = defaultAccount; //support old project var r = { contractId: t.contractId, functionId: t.functionId, @@ -40,7 +42,8 @@ Item { gas: QEtherHelper.createBigInt(t.gas.value), gasPrice: QEtherHelper.createEther(t.gasPrice.value, t.gasPrice.unit), stdContract: t.stdContract, - parameters: {} + parameters: {}, + sender: t.sender }; var qType = []; for (var key in t.parameters) @@ -189,11 +192,12 @@ Item { }; } - function newAccount(_balance, _unit) + function newAccount(_balance, _unit, _secret) { - var secret = clientModel.newAddress(); - var name = qsTr("Account") + "-" + secret.substring(0, 4); - return { name: name, secret: secret, balance: QEtherHelper.createEther(_balance, _unit) }; + if (!_secret) + _secret = clientModel.newAddress(); + var name = qsTr("Account") + "-" + _secret.substring(0, 4); + return { name: name, secret: _secret, balance: QEtherHelper.createEther(_balance, _unit) }; } function createDefaultState() { @@ -203,7 +207,7 @@ Item { accounts: [] }; - item.accounts.push(newAccount("1000000", QEther.Ether)); + item.accounts.push(newAccount("1000000", QEther.Ether, defaultAccount)); //add all stdc contracts for (var i = 0; i < contractLibrary.model.count; i++) { @@ -213,6 +217,7 @@ Item { 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); }; @@ -221,6 +226,7 @@ Item { var ctorTr = defaultTransactionItem(); ctorTr.functionId = c; ctorTr.contractId = c; + ctorTr.sender = item.accounts[0].secret; item.transactions.push(ctorTr); } return item; From 7bb5032874399793746ef757e873d50ea4a8c2cd Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 3 Mar 2015 16:46:09 +0100 Subject: [PATCH 30/54] - small changes --- mix/ClientModel.cpp | 1 - mix/MixClient.cpp | 1 - mix/qml/StateListModel.qml | 6 +++--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index ab7b5c7ea..9c6255b6e 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -190,7 +190,6 @@ void ClientModel::setupState(QVariantMap _state) if (contractId.isEmpty() && m_context->codeModel()->hasContract()) //TODO: This is to support old project files, remove later contractId = m_context->codeModel()->contracts().keys()[0]; QVariantList qParams = transaction.value("qType").toList(); - TransactionSettings transactionSettings(contractId, functionId, value, gas, gasPrice, Secret(sender.toStdString())); for (QVariant const& variant: qParams) diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 7b38a3743..aaa37a8bb 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -21,7 +21,6 @@ */ #include -#include #include #include #include diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index c2eb43bc1..61307826c 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -11,10 +11,10 @@ Item { property alias model: stateListModel property var stateList: [] - property string defaultAccount: "cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074" + property string defaultAccount: "cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074" //support for old project function fromPlainStateItem(s) { if (!s.accounts) - s.accounts = [stateListModel.newAccount("1000000", QEther.Ether, defaultAccount)]; //support old project + s.accounts = [stateListModel.newAccount("1000000", QEther.Ether, defaultAccount)]; //support for old project return { title: s.title, transactions: s.transactions.map(fromPlainTransactionItem), @@ -33,7 +33,7 @@ Item { function fromPlainTransactionItem(t) { if (!t.sender) - t.sender = defaultAccount; //support old project + t.sender = defaultAccount; //support for old project var r = { contractId: t.contractId, functionId: t.functionId, From 44ae13bdeb9e91f4c82c2e8f837977ab76e13d48 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 3 Mar 2015 16:54:46 +0100 Subject: [PATCH 31/54] small changes --- mix/ClientModel.cpp | 2 +- mix/ClientModel.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 9c6255b6e..8119ea77a 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -207,7 +207,7 @@ void ClientModel::setupState(QVariantMap _state) executeSequence(transactionSequence, accounts); } -void ClientModel::executeSequence(std::vector const& _sequence, std::map _balances) +void ClientModel::executeSequence(std::vector const& _sequence, std::map const& _balances) { if (m_running) BOOST_THROW_EXCEPTION(ExecutionStateException()); diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 9af8f0aff..6ec00d20a 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -193,7 +193,7 @@ signals: private: RecordLogEntry* lastBlock() const; QVariantMap contractAddresses() const; - void executeSequence(std::vector const& _sequence, std::map _balances); + void executeSequence(std::vector const& _sequence, std::map const& _balances); dev::Address deployContract(bytes const& _code, TransactionSettings const& _tr = TransactionSettings()); void callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr); void onNewTransaction(); From 5f191f4f895bac5d56e52f05df58a65d3f738226 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 3 Mar 2015 16:45:23 +0100 Subject: [PATCH 32/54] Indentation style fixes --- libdevcore/StructuredLogger.h | 24 ++++++++++++++++-------- libethereum/Client.h | 9 +++++++-- libp2p/Host.h | 6 ++++-- libwebthree/WebThree.cpp | 15 ++++++++++----- libwebthree/WebThree.h | 13 +++++++++---- 5 files changed, 46 insertions(+), 21 deletions(-) diff --git a/libdevcore/StructuredLogger.h b/libdevcore/StructuredLogger.h index 288e468f3..58b408ede 100644 --- a/libdevcore/StructuredLogger.h +++ b/libdevcore/StructuredLogger.h @@ -59,25 +59,33 @@ public: static void starting(std::string const& _clientImpl, const char* _ethVersion); static void stopping(std::string const& _clientImpl, const char* _ethVersion); - static void p2pConnected(std::string const& _id, + static void p2pConnected( + std::string const& _id, bi::tcp::endpoint const& _addr, std::chrono::system_clock::time_point const& _ts, std::string const& _remoteVersion, - unsigned int _numConnections); + unsigned int _numConnections + ); static void p2pDisconnected(std::string const& _id, bi::tcp::endpoint const& _addr, unsigned int _numConnections); - static void minedNewBlock(std::string const& _hash, + static void minedNewBlock( + std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, - std::string const& _prevHash); - static void chainReceivedNewBlock(std::string const& _hash, + std::string const& _prevHash + ); + static void chainReceivedNewBlock( + std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, std::string const& _remoteID, - std::string const& _prevHash); - static void chainNewHead(std::string const& _hash, + std::string const& _prevHash + ); + static void chainNewHead( + std::string const& _hash, std::string const& _blockNumber, std::string const& _chainHeadHash, - std::string const& _prevHash); + std::string const& _prevHash + ); static void transactionReceived(std::string const& _hash, std::string const& _remoteId); private: // Singleton class. Private default ctor and no copying diff --git a/libethereum/Client.h b/libethereum/Client.h index 31aa1aee3..87c1c67fa 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -167,8 +167,13 @@ class Client: public MinerHost, public Interface, Worker public: /// New-style Constructor. - explicit Client(p2p::Host* _host, std::string const& _dbPath = std::string(), bool _forceClean = false, - u256 _networkId = 0, int _miners = -1); + explicit Client( + p2p::Host* _host, + std::string const& _dbPath = std::string(), + bool _forceClean = false, + u256 _networkId = 0, + int _miners = -1 + ); /// Destructor. virtual ~Client(); diff --git a/libp2p/Host.h b/libp2p/Host.h index 6f5c5a50c..0eefa6f90 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -85,8 +85,10 @@ class Host: public Worker public: /// Start server, listening for connections on the given port. - Host(std::string const& _clientVersion, NetworkPreferences const& _n = NetworkPreferences(), - bytesConstRef _restoreNetwork = bytesConstRef()); + Host(std::string const& _clientVersion, + NetworkPreferences const& _n = NetworkPreferences(), + bytesConstRef _restoreNetwork = bytesConstRef() + ); /// Will block on network process events. virtual ~Host(); diff --git a/libwebthree/WebThree.cpp b/libwebthree/WebThree.cpp index c97e4b5c8..1cf478746 100644 --- a/libwebthree/WebThree.cpp +++ b/libwebthree/WebThree.cpp @@ -35,11 +35,16 @@ using namespace dev::p2p; using namespace dev::eth; using namespace dev::shh; -WebThreeDirect::WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean, - std::set const& _interfaces, NetworkPreferences const& _n, - bytesConstRef _network, int _miners): - m_clientVersion(_clientVersion), - m_net(_clientVersion, _n, _network) +WebThreeDirect::WebThreeDirect( + std::string const& _clientVersion, + std::string const& _dbPath, + bool _forceClean, + std::set const& _interfaces, + NetworkPreferences const& _n, + bytesConstRef _network, int _miners +): + m_clientVersion(_clientVersion), + m_net(_clientVersion, _n, _network) { if (_dbPath.size()) Defaults::setDBPath(_dbPath); diff --git a/libwebthree/WebThree.h b/libwebthree/WebThree.h index 9eb9111b4..66cd4c556 100644 --- a/libwebthree/WebThree.h +++ b/libwebthree/WebThree.h @@ -103,10 +103,15 @@ class WebThreeDirect : public WebThreeNetworkFace public: /// Constructor for private instance. If there is already another process on the machine using @a _dbPath, then this will throw an exception. /// ethereum() may be safely static_cast()ed to a eth::Client*. - WebThreeDirect(std::string const& _clientVersion, std::string const& _dbPath, bool _forceClean = false, - std::set const& _interfaces = {"eth", "shh"}, - p2p::NetworkPreferences const& _n = p2p::NetworkPreferences(), - bytesConstRef _network = bytesConstRef(), int _miners = -1); + WebThreeDirect( + std::string const& _clientVersion, + std::string const& _dbPath, + bool _forceClean = false, + std::set const& _interfaces = {"eth", "shh"}, + p2p::NetworkPreferences const& _n = p2p::NetworkPreferences(), + bytesConstRef _network = bytesConstRef(), + int _miners = -1 + ); /// Destructor. ~WebThreeDirect(); From ce2cf330f08b9c056cbe18082fa33092eedab89b Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 3 Mar 2015 17:32:33 +0100 Subject: [PATCH 33/54] - Small Changes --- mix/ClientModel.h | 1 - mix/qml/StateDialog.qml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 6ec00d20a..8810502bd 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -27,7 +27,6 @@ #include #include #include -#include "QBigInt.h" #include "MachineStates.h" namespace dev diff --git a/mix/qml/StateDialog.qml b/mix/qml/StateDialog.qml index 21b441845..4d890fe18 100644 --- a/mix/qml/StateDialog.qml +++ b/mix/qml/StateDialog.qml @@ -161,7 +161,7 @@ Window { Action { id: deleteAccountAction - tooltip: qsTr("delete Account") + tooltip: qsTr("Delete Account") onTriggered: { if (transactionsModel.isUsed(stateAccounts[styleData.row].secret)) From 6e60c118b7d05192e8f3b596df2bac9b3e9842d4 Mon Sep 17 00:00:00 2001 From: winsvega Date: Sat, 28 Feb 2015 20:57:01 +0300 Subject: [PATCH 34/54] Transaction Tests A few changes --- test/TestHelper.cpp | 2 +- test/transaction.cpp | 2 +- test/ttTransactionTestFiller.json | 31 +++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index ea44111c9..f82b72b88 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -170,7 +170,7 @@ void ImportTest::importTransaction(json_spirit::mObject& _o) } } -void ImportTest::exportTest(bytes _output, State& _statePost) +void ImportTest::exportTest(bytes const& _output, State const& _statePost) { // export output m_TestObject["out"] = "0x" + toHex(_output); diff --git a/test/transaction.cpp b/test/transaction.cpp index c7a0e61d7..8cda18f1e 100644 --- a/test/transaction.cpp +++ b/test/transaction.cpp @@ -104,7 +104,7 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) BOOST_AUTO_TEST_SUITE(TransactionTests) -BOOST_AUTO_TEST_CASE(TransactionTest) +BOOST_AUTO_TEST_CASE(ttTransactionTest) { dev::test::executeTests("ttTransactionTest", "/TransactionTests", dev::test::doTransactionTests); } diff --git a/test/ttTransactionTestFiller.json b/test/ttTransactionTestFiller.json index 23a384d50..96e4c78a6 100644 --- a/test/ttTransactionTestFiller.json +++ b/test/ttTransactionTestFiller.json @@ -59,6 +59,21 @@ } }, + "WrongVRSTestVOverflow" : { + "transaction" : + { + "data" : "", + "gasLimit" : "2000", + "gasPrice" : "1", + "nonce" : "0", + "to" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "value" : "10", + "v" : "310", + "r" : "0x98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a", + "s" : "0x8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3" + } + }, + "WrongVRSTestIncorrectSize" : { "transaction" : { @@ -91,6 +106,22 @@ } }, + "DataTest" : { + "transaction" : + { + "data" : "0x0358ac39584bc98a7c979f984b03", + "gasLimit" : "850", + "gasPrice" : "1", + "nonce" : "0", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10", + "v" : "27", + "r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353", + "s" : "secretkey 45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "s" : "0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804" + } + }, + "TransactionWithTooManyRLPElements" : { "transaction" : { From 3e7e391b57861a135894be635e185df147da552a Mon Sep 17 00:00:00 2001 From: winsvega Date: Mon, 2 Mar 2015 18:18:28 +0300 Subject: [PATCH 35/54] Test Cases Changes userDefinedFile test now goes with --test option for all cases --- test/block.cpp | 144 ++++++++++++++++++++++--------------------- test/state.cpp | 2 +- test/transaction.cpp | 4 +- test/vm.cpp | 4 +- 4 files changed, 78 insertions(+), 76 deletions(-) diff --git a/test/block.cpp b/test/block.cpp index fdf65affa..7c50eef4d 100644 --- a/test/block.cpp +++ b/test/block.cpp @@ -81,6 +81,76 @@ bytes createBlockRLPFromFields(mObject& _tObj) return rlpStream.out(); } +void overwriteBlockHeader(mObject& _o, BlockInfo _current_BlockHeader) +{ + if (_o.count("blockHeader")) + { + if (_o["blockHeader"].get_obj().size() != 14) + { + + BlockInfo tmp = _current_BlockHeader; + + if (_o["blockHeader"].get_obj().count("parentHash")) + tmp.parentHash = h256(_o["blockHeader"].get_obj()["parentHash"].get_str()); + + if (_o["blockHeader"].get_obj().count("uncleHash")) + tmp.sha3Uncles = h256(_o["blockHeader"].get_obj()["uncleHash"].get_str()); + + if (_o["blockHeader"].get_obj().count("coinbase")) + tmp.coinbaseAddress = Address(_o["blockHeader"].get_obj()["coinbase"].get_str()); + + if (_o["blockHeader"].get_obj().count("stateRoot")) + tmp.stateRoot = h256(_o["blockHeader"].get_obj()["stateRoot"].get_str()); + + if (_o["blockHeader"].get_obj().count("transactionsTrie")) + tmp.transactionsRoot = h256(_o["blockHeader"].get_obj()["transactionsTrie"].get_str()); + + if (_o["blockHeader"].get_obj().count("receiptTrie")) + tmp.receiptsRoot = h256(_o["blockHeader"].get_obj()["receiptTrie"].get_str()); + + if (_o["blockHeader"].get_obj().count("bloom")) + tmp.logBloom = LogBloom(_o["blockHeader"].get_obj()["bloom"].get_str()); + + if (_o["blockHeader"].get_obj().count("difficulty")) + tmp.difficulty = toInt(_o["blockHeader"].get_obj()["difficulty"]); + + if (_o["blockHeader"].get_obj().count("number")) + tmp.number = toInt(_o["blockHeader"].get_obj()["number"]); + + if (_o["blockHeader"].get_obj().count("gasLimit")) + tmp.gasLimit = toInt(_o["blockHeader"].get_obj()["gasLimit"]); + + if (_o["blockHeader"].get_obj().count("gasUsed")) + tmp.gasUsed = toInt(_o["blockHeader"].get_obj()["gasUsed"]); + + if (_o["blockHeader"].get_obj().count("timestamp")) + tmp.timestamp = toInt(_o["blockHeader"].get_obj()["timestamp"]); + + if (_o["blockHeader"].get_obj().count("extraData")) + tmp.extraData = importByteArray(_o["blockHeader"].get_obj()["extraData"].get_str()); + + // find new valid nonce + + if (tmp != _current_BlockHeader) + { + _current_BlockHeader = tmp; + cout << "new header!\n"; + ProofOfWork pow; + MineInfo ret; + while (!ProofOfWork::verify(_current_BlockHeader.headerHash(WithoutNonce), _current_BlockHeader.nonce, _current_BlockHeader.difficulty)) + tie(ret, _current_BlockHeader.nonce) = pow.mine(_current_BlockHeader.headerHash(WithoutNonce), _current_BlockHeader.difficulty, 10000, true, true); + } + } + else + { + // take the blockheader as is + const bytes c_blockRLP = createBlockRLPFromFields(_o["blockHeader"].get_obj()); + const RLP c_bRLP(c_blockRLP); + _current_BlockHeader.populateFromHeader(c_bRLP, false); + } + } +} + void doBlockTests(json_spirit::mValue& _v, bool _fillin) { for (auto& i: _v.get_obj()) @@ -214,76 +284,9 @@ void doBlockTests(json_spirit::mValue& _v, bool _fillin) BlockInfo current_BlockHeader = state.info(); // overwrite blockheader with (possible wrong) data from "blockheader" in filler; - - if (o.count("blockHeader")) - { - if (o["blockHeader"].get_obj().size() != 14) - { - - BlockInfo tmp = current_BlockHeader; - - if (o["blockHeader"].get_obj().count("parentHash")) - tmp.parentHash = h256(o["blockHeader"].get_obj()["parentHash"].get_str()); - - if (o["blockHeader"].get_obj().count("uncleHash")) - tmp.sha3Uncles = h256(o["blockHeader"].get_obj()["uncleHash"].get_str()); - - if (o["blockHeader"].get_obj().count("coinbase")) - tmp.coinbaseAddress = Address(o["blockHeader"].get_obj()["coinbase"].get_str()); - - if (o["blockHeader"].get_obj().count("stateRoot")) - tmp.stateRoot = h256(o["blockHeader"].get_obj()["stateRoot"].get_str()); - - if (o["blockHeader"].get_obj().count("transactionsTrie")) - tmp.transactionsRoot = h256(o["blockHeader"].get_obj()["transactionsTrie"].get_str()); - - if (o["blockHeader"].get_obj().count("receiptTrie")) - tmp.receiptsRoot = h256(o["blockHeader"].get_obj()["receiptTrie"].get_str()); - - if (o["blockHeader"].get_obj().count("bloom")) - tmp.logBloom = LogBloom(o["blockHeader"].get_obj()["bloom"].get_str()); - - if (o["blockHeader"].get_obj().count("difficulty")) - tmp.difficulty = toInt(o["blockHeader"].get_obj()["difficulty"]); - - if (o["blockHeader"].get_obj().count("number")) - tmp.number = toInt(o["blockHeader"].get_obj()["number"]); - - if (o["blockHeader"].get_obj().count("gasLimit")) - tmp.gasLimit = toInt(o["blockHeader"].get_obj()["gasLimit"]); - - if (o["blockHeader"].get_obj().count("gasUsed")) - tmp.gasUsed = toInt(o["blockHeader"].get_obj()["gasUsed"]); - - if (o["blockHeader"].get_obj().count("timestamp")) - tmp.timestamp = toInt(o["blockHeader"].get_obj()["timestamp"]); - - if (o["blockHeader"].get_obj().count("extraData")) - tmp.extraData = importByteArray(o["blockHeader"].get_obj()["extraData"].get_str()); - - // find new valid nonce - - if (tmp != current_BlockHeader) - { - current_BlockHeader = tmp; - cout << "new header!\n"; - ProofOfWork pow; - MineInfo ret; - while (!ProofOfWork::verify(current_BlockHeader.headerHash(WithoutNonce), current_BlockHeader.nonce, current_BlockHeader.difficulty)) - tie(ret, current_BlockHeader.nonce) = pow.mine(current_BlockHeader.headerHash(WithoutNonce), current_BlockHeader.difficulty, 10000, true, true); - } - } - else - { - // take the blockheader as is - const bytes c_blockRLP = createBlockRLPFromFields(o["blockHeader"].get_obj()); - const RLP c_bRLP(c_blockRLP); - current_BlockHeader.populateFromHeader(c_bRLP, false); - } - } + overwriteBlockHeader(o, current_BlockHeader); // write block header - mObject oBlockHeader; oBlockHeader["parentHash"] = toString(current_BlockHeader.parentHash); oBlockHeader["uncleHash"] = toString(current_BlockHeader.sha3Uncles); @@ -423,7 +426,6 @@ void doBlockTests(json_spirit::mValue& _v, bool _fillin) BOOST_CHECK_MESSAGE(blockHeaderFromFields == blockFromRlp, "However, blockHeaderFromFields != blockFromRlp!"); //Check transaction list - Transactions txsFromField; for (auto const& txObj: o["transactions"].get_array()) @@ -511,9 +513,9 @@ BOOST_AUTO_TEST_CASE(blForkBlocks) dev::test::executeTests("blForkBlocks", "/BlockTests", dev::test::doBlockTests); } -BOOST_AUTO_TEST_CASE(userDefinedFileBl) +BOOST_AUTO_TEST_CASE(userDefinedFile) { - dev::test::userDefinedTest("--bltest", dev::test::doBlockTests); + dev::test::userDefinedTest("--singletest", dev::test::doBlockTests); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/state.cpp b/test/state.cpp index 1581e4055..fe133822a 100644 --- a/test/state.cpp +++ b/test/state.cpp @@ -241,7 +241,7 @@ BOOST_AUTO_TEST_CASE(stCreateTest) BOOST_AUTO_TEST_CASE(userDefinedFileState) { - dev::test::userDefinedTest("--statetest", dev::test::doStateTests); + dev::test::userDefinedTest("--singletest", dev::test::doStateTests); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/transaction.cpp b/test/transaction.cpp index 8cda18f1e..83fd8da4d 100644 --- a/test/transaction.cpp +++ b/test/transaction.cpp @@ -167,9 +167,9 @@ BOOST_AUTO_TEST_CASE(ttCreateTest) } } -BOOST_AUTO_TEST_CASE(userDefinedFileTT) +BOOST_AUTO_TEST_CASE(userDefinedFile) { - dev::test::userDefinedTest("--ttTest", dev::test::doTransactionTests); + dev::test::userDefinedTest("--singletest", dev::test::doTransactionTests); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/vm.cpp b/test/vm.cpp index 21bea0650..16f7385a0 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -592,9 +592,9 @@ BOOST_AUTO_TEST_CASE(vmRandom) } } -BOOST_AUTO_TEST_CASE(userDefinedFileVM) +BOOST_AUTO_TEST_CASE(userDefinedFile) { - dev::test::userDefinedTest("--vmtest", dev::test::doVMTests); + dev::test::userDefinedTest("--singletest", dev::test::doVMTests); } BOOST_AUTO_TEST_SUITE_END() From 0c16c19a1fc59d4161dba9b8a5e7a3ddbf777289 Mon Sep 17 00:00:00 2001 From: winsvega Date: Mon, 2 Mar 2015 18:21:41 +0300 Subject: [PATCH 36/54] Transaction Tests missing TestHelper.h file --- test/TestHelper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/TestHelper.h b/test/TestHelper.h index c4dde1a60..3707a5fff 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -52,7 +52,7 @@ public: void importEnv(json_spirit::mObject& _o); void importState(json_spirit::mObject& _o, eth::State& _state); void importTransaction(json_spirit::mObject& _o); - void exportTest(bytes _output, eth::State& _statePost); + void exportTest(bytes const& _output, eth::State const& _statePost); eth::State m_statePre; eth::State m_statePost; From 0807e2ee7c32d10f86622c7cd143b6ae37005f48 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 4 Mar 2015 01:17:08 +0100 Subject: [PATCH 38/54] Squashed 'libjsqrc/ethereumjs/' changes from 5bd166c..7d6b35a 7d6b35a Merge branch 'master' into cpp 9b3a0f0 Merge branch 'event_hash' 9887972 version 63dcee6 ignore for maxcomplexity warning 8376bfa gulp a59f3a4 Merge pull request #85 from ethers/abiString 0dd6cc4 gulp 688faec Merge pull request #81 from ethers/arraySupport 64f6630 updated README.md 4f9aaec Merge pull request #94 from ethereum/signature 91321fb removed web3 dependency from abi.js 5c7d8a7 separated event signature 81b19cc event hash ea250e6 Merge commit 'be3bfb76bef1d1f113033cd9093e03a00066d5d1' into ethereumjs_timeout c08cea1 Improvement to AZ - confirmation disabler. Fix network crash. git-subtree-dir: libjsqrc/ethereumjs git-subtree-split: 7d6b35af1c2b59feae5a01c899fae68298d71211 --- README.md | 9 +- bower.json | 2 +- dist/ethereum.js | 142 ++++++++++++++++++---------- dist/ethereum.js.map | 12 ++- dist/ethereum.min.js | 2 +- lib/abi.js | 57 +++++------ lib/contract.js | 11 ++- lib/event.js | 10 +- lib/httpsync.js | 2 +- lib/signature.js | 42 +++++++++ package.json | 2 +- test/abi.inputParser.js | 203 ++++++++++++++++++++++++++++++++-------- 12 files changed, 345 insertions(+), 149 deletions(-) create mode 100644 lib/signature.js diff --git a/README.md b/README.md index 7fe6ee863..30c20aafa 100644 --- a/README.md +++ b/README.md @@ -75,14 +75,13 @@ npm test **Please note this repo is in it's early stage.** -If you'd like to run a WebSocket ethereum node check out -[go-ethereum](https://github.com/ethereum/go-ethereum). +If you'd like to run a Http ethereum node check out +[cpp-ethereum](https://github.com/ethereum/cpp-ethereum). -To install ethereum and spawn a node: +Install ethereum and spawn a node: ``` -go get github.com/ethereum/go-ethereum/ethereum -ethereum -ws -loglevel=4 +eth -j ``` [npm-image]: https://badge.fury.io/js/ethereum.js.png diff --git a/bower.json b/bower.json index b279d322b..f0cb33321 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "ethereum.js", "namespace": "ethereum", - "version": "0.0.15", + "version": "0.0.16", "description": "Ethereum Compatible JavaScript API", "main": [ "./dist/ethereum.js", diff --git a/dist/ethereum.js b/dist/ethereum.js index a0294e183..41ab0b99a 100644 --- a/dist/ethereum.js +++ b/dist/ethereum.js @@ -22,7 +22,6 @@ require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof requ * @date 2014 */ -var web3 = require('./web3'); var utils = require('./utils'); var types = require('./types'); var c = require('./const'); @@ -41,11 +40,11 @@ var arrayType = function (type) { var dynamicTypeBytes = function (type, value) { // TODO: decide what to do with array of strings if (arrayType(type) || type === 'string') // only string itself that is dynamic; stringX is static length. - return f.formatInputInt(value.length); + return f.formatInputInt(value.length); return ""; }; -var inputTypes = types.inputTypes(); +var inputTypes = types.inputTypes(); /// Formats input params to bytes /// @param abi contract method inputs @@ -53,13 +52,16 @@ var inputTypes = types.inputTypes(); /// @returns bytes representation of input params var formatInput = function (inputs, params) { var bytes = ""; + var toAppendConstant = ""; + var toAppendArrayContent = ""; - /// first we iterate in search for dynamic + /// first we iterate in search for dynamic inputs.forEach(function (input, index) { bytes += dynamicTypeBytes(input.type, params[index]); }); inputs.forEach(function (input, i) { + /*jshint maxcomplexity:5 */ var typeMatch = false; for (var j = 0; j < inputTypes.length && !typeMatch; j++) { typeMatch = inputTypes[j].type(inputs[i].type, params[i]); @@ -69,17 +71,19 @@ var formatInput = function (inputs, params) { } var formatter = inputTypes[j - 1].format; - var toAppend = ""; if (arrayType(inputs[i].type)) - toAppend = params[i].reduce(function (acc, curr) { + toAppendArrayContent += params[i].reduce(function (acc, curr) { return acc + formatter(curr); }, ""); + else if (inputs[i].type === 'string') + toAppendArrayContent += formatter(params[i]); else - toAppend = formatter(params[i]); - - bytes += toAppend; + toAppendConstant += formatter(params[i]); }); + + bytes += toAppendConstant + toAppendArrayContent; + return bytes; }; @@ -89,14 +93,14 @@ var dynamicBytesLength = function (type) { return 0; }; -var outputTypes = types.outputTypes(); +var outputTypes = types.outputTypes(); /// Formats output bytes back to param list /// @param contract abi method outputs -/// @param bytes representtion of output -/// @returns array of output params +/// @param bytes representtion of output +/// @returns array of output params var formatOutput = function (outs, output) { - + output = output.slice(2); var result = []; var padding = c.ETH_PADDING * 2; @@ -104,7 +108,7 @@ var formatOutput = function (outs, output) { var dynamicPartLength = outs.reduce(function (acc, curr) { return acc + dynamicBytesLength(curr.type); }, 0); - + var dynamicPart = output.slice(0, dynamicPartLength); output = output.slice(dynamicPartLength); @@ -125,13 +129,13 @@ var formatOutput = function (outs, output) { dynamicPart = dynamicPart.slice(padding); var array = []; for (var k = 0; k < size; k++) { - array.push(formatter(output.slice(0, padding))); + array.push(formatter(output.slice(0, padding))); output = output.slice(padding); } result.push(array); } else if (types.prefixedType('string')(outs[i].type)) { - dynamicPart = dynamicPart.slice(padding); + dynamicPart = dynamicPart.slice(padding); result.push(formatter(output.slice(0, padding))); output = output.slice(padding); } else { @@ -149,14 +153,14 @@ var formatOutput = function (outs, output) { var inputParser = function (json) { var parser = {}; json.forEach(function (method) { - var displayName = utils.extractDisplayName(method.name); + var displayName = utils.extractDisplayName(method.name); var typeName = utils.extractTypeName(method.name); var impl = function () { var params = Array.prototype.slice.call(arguments); return formatInput(method.inputs, params); }; - + if (parser[displayName] === undefined) { parser[displayName] = impl; } @@ -173,7 +177,7 @@ var outputParser = function (json) { var parser = {}; json.forEach(function (method) { - var displayName = utils.extractDisplayName(method.name); + var displayName = utils.extractDisplayName(method.name); var typeName = utils.extractTypeName(method.name); var impl = function (output) { @@ -190,27 +194,14 @@ var outputParser = function (json) { return parser; }; -/// @param function/event name for which we want to get signature -/// @returns signature of function/event with given name -var signatureFromAscii = function (name) { - return web3.sha3(web3.fromAscii(name)).slice(0, 2 + c.ETH_SIGNATURE_LENGTH * 2); -}; - -var eventSignatureFromAscii = function (name) { - return web3.sha3(web3.fromAscii(name)); -}; - module.exports = { inputParser: inputParser, outputParser: outputParser, formatInput: formatInput, - formatOutput: formatOutput, - signatureFromAscii: signatureFromAscii, - eventSignatureFromAscii: eventSignatureFromAscii + formatOutput: formatOutput }; - -},{"./const":2,"./formatters":8,"./types":14,"./utils":15,"./web3":17}],2:[function(require,module,exports){ +},{"./const":2,"./formatters":8,"./types":15,"./utils":16}],2:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -296,6 +287,7 @@ var web3 = require('./web3'); var abi = require('./abi'); var utils = require('./utils'); var eventImpl = require('./event'); +var signature = require('./signature'); var exportNatspecGlobals = function (vars) { // it's used byt natspec.js @@ -343,12 +335,12 @@ var addFunctionsToContract = function (contract, desc, address) { var impl = function () { /*jshint maxcomplexity:7 */ var params = Array.prototype.slice.call(arguments); - var signature = abi.signatureFromAscii(method.name); + var sign = signature.functionSignatureFromAscii(method.name); var parsed = inputParser[displayName][typeName].apply(null, params); var options = contract._options || {}; options.to = address; - options.data = signature + parsed; + options.data = sign + parsed; var isTransact = contract._isTransact === true || (contract._isTransact !== false && !method.constant); var collapse = options.collapse !== false; @@ -402,7 +394,7 @@ var addEventRelatedPropertiesToContract = function (contract, desc, address) { Object.defineProperty(contract, 'topic', { get: function() { return utils.filterEvents(desc).map(function (e) { - return abi.eventSignatureFromAscii(e.name); + return signature.eventSignatureFromAscii(e.name); }); } }); @@ -415,8 +407,8 @@ var addEventsToContract = function (contract, desc, address) { var impl = function () { var params = Array.prototype.slice.call(arguments); - var signature = abi.eventSignatureFromAscii(e.name); - var event = eventImpl.inputParser(address, signature, e); + var sign = signature.eventSignatureFromAscii(e.name); + var event = eventImpl.inputParser(address, sign, e); var o = event.apply(null, params); var outputFormatter = function (data) { var parser = eventImpl.outputParser(e); @@ -489,7 +481,7 @@ var contract = function (address, desc) { module.exports = contract; -},{"./abi":1,"./event":6,"./utils":15,"./web3":17}],4:[function(require,module,exports){ +},{"./abi":1,"./event":6,"./signature":14,"./utils":16,"./web3":18}],4:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -638,6 +630,7 @@ module.exports = { var abi = require('./abi'); var utils = require('./utils'); +var signature = require('./signature'); /// filter inputs array && returns only indexed (or not) inputs /// @param inputs array @@ -676,14 +669,14 @@ var indexedParamsToTopics = function (event, indexed) { }); }; -var inputParser = function (address, signature, event) { +var inputParser = function (address, sign, event) { // valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.watch' return function (indexed, options) { var o = options || {}; o.address = address; o.topic = []; - o.topic.push(signature); + o.topic.push(sign); if (indexed) { o.topic = o.topic.concat(indexedParamsToTopics(event, indexed)); } @@ -712,6 +705,7 @@ var outputParser = function (event) { var result = { event: utils.extractDisplayName(event.name), number: output.number, + hash: output.hash, args: {} }; @@ -735,8 +729,8 @@ var outputParser = function (event) { var getMatchingEvent = function (events, payload) { for (var i = 0; i < events.length; i++) { - var signature = abi.eventSignatureFromAscii(events[i].name); - if (signature === payload.topic[0]) { + var sign = signature.eventSignatureFromAscii(events[i].name); + if (sign === payload.topic[0]) { return events[i]; } } @@ -751,7 +745,7 @@ module.exports = { }; -},{"./abi":1,"./utils":15}],7:[function(require,module,exports){ +},{"./abi":1,"./signature":14,"./utils":16}],7:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1023,7 +1017,7 @@ module.exports = { }; -},{"./const":2,"./utils":15}],9:[function(require,module,exports){ +},{"./const":2,"./utils":16}],9:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1053,7 +1047,7 @@ if ("build" !== 'build') {/* var HttpSyncProvider = function (host) { this.handlers = []; - this.host = host || 'http://localhost:8080'; + this.host = host || 'http://127.0.0.1:8080'; }; HttpSyncProvider.prototype.send = function (payload) { @@ -1345,6 +1339,50 @@ module.exports = { You should have received a copy of the GNU Lesser General Public License along with ethereum.js. If not, see . */ +/** @file signature.js + * @authors: + * Marek Kotewicz + * @date 2015 + */ + +var web3 = require('./web3'); +var c = require('./const'); + +/// @param function name for which we want to get signature +/// @returns signature of function with given name +var functionSignatureFromAscii = function (name) { + return web3.sha3(web3.fromAscii(name)).slice(0, 2 + c.ETH_SIGNATURE_LENGTH * 2); +}; + +/// @param event name for which we want to get signature +/// @returns signature of event with given name +var eventSignatureFromAscii = function (name) { + return web3.sha3(web3.fromAscii(name)); +}; + +module.exports = { + functionSignatureFromAscii: functionSignatureFromAscii, + eventSignatureFromAscii: eventSignatureFromAscii +}; + + +},{"./const":2,"./web3":18}],15:[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 types.js * @authors: * Marek Kotewicz @@ -1409,7 +1447,7 @@ module.exports = { }; -},{"./formatters":8}],15:[function(require,module,exports){ +},{"./formatters":8}],16:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1554,7 +1592,7 @@ module.exports = { }; -},{"./const":2}],16:[function(require,module,exports){ +},{"./const":2}],17:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1605,7 +1643,7 @@ module.exports = { }; -},{}],17:[function(require,module,exports){ +},{}],18:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1796,7 +1834,7 @@ setupMethods(shhWatch, watches.shh()); module.exports = web3; -},{"./db":4,"./eth":5,"./filter":7,"./requestmanager":12,"./shh":13,"./utils":15,"./watches":16}],"web3":[function(require,module,exports){ +},{"./db":4,"./eth":5,"./filter":7,"./requestmanager":12,"./shh":13,"./utils":16,"./watches":17}],"web3":[function(require,module,exports){ var web3 = require('./lib/web3'); web3.providers.HttpSyncProvider = require('./lib/httpsync'); web3.providers.QtSyncProvider = require('./lib/qtsync'); @@ -1805,7 +1843,7 @@ web3.abi = require('./lib/abi'); module.exports = web3; -},{"./lib/abi":1,"./lib/contract":3,"./lib/httpsync":9,"./lib/qtsync":11,"./lib/web3":17}]},{},["web3"]) +},{"./lib/abi":1,"./lib/contract":3,"./lib/httpsync":9,"./lib/qtsync":11,"./lib/web3":18}]},{},["web3"]) //# sourceMappingURL=ethereum.js.map \ No newline at end of file diff --git a/dist/ethereum.js.map b/dist/ethereum.js.map index 8b58a0fcd..1cb7bbd3f 100644 --- a/dist/ethereum.js.map +++ b/dist/ethereum.js.map @@ -15,6 +15,7 @@ "lib/qtsync.js", "lib/requestmanager.js", "lib/shh.js", + "lib/signature.js", "lib/types.js", "lib/utils.js", "lib/watches.js", @@ -22,24 +23,25 @@ "index.js" ], "names": [], - "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;ACnCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;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;;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;AChHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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/EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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/IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7LA;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;;ACzMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;ACnCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;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;;ACjEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;AChHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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/EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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/IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7LA;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/** @file abi.js\n * @authors:\n * Marek Kotewicz \n * Gav Wood \n * @date 2014\n */\n\nvar web3 = require('./web3'); \nvar utils = require('./utils');\nvar types = require('./types');\nvar c = require('./const');\nvar f = require('./formatters');\n\nvar displayTypeError = function (type) {\n console.error('parser does not support type: ' + type);\n};\n\n/// This method should be called if we want to check if givent type is an array type\n/// @returns true if it is, otherwise false\nvar arrayType = function (type) {\n return type.slice(-2) === '[]';\n};\n\nvar dynamicTypeBytes = function (type, value) {\n // TODO: decide what to do with array of strings\n if (arrayType(type) || type === 'string') // only string itself that is dynamic; stringX is static length.\n return f.formatInputInt(value.length); \n return \"\";\n};\n\nvar inputTypes = types.inputTypes(); \n\n/// Formats input params to bytes\n/// @param abi contract method inputs\n/// @param array of params that will be formatted to bytes\n/// @returns bytes representation of input params\nvar formatInput = function (inputs, params) {\n var bytes = \"\";\n\n /// first we iterate in search for dynamic \n inputs.forEach(function (input, index) {\n bytes += dynamicTypeBytes(input.type, params[index]);\n });\n\n inputs.forEach(function (input, i) {\n var typeMatch = false;\n for (var j = 0; j < inputTypes.length && !typeMatch; j++) {\n typeMatch = inputTypes[j].type(inputs[i].type, params[i]);\n }\n if (!typeMatch) {\n displayTypeError(inputs[i].type);\n }\n\n var formatter = inputTypes[j - 1].format;\n var toAppend = \"\";\n\n if (arrayType(inputs[i].type))\n toAppend = params[i].reduce(function (acc, curr) {\n return acc + formatter(curr);\n }, \"\");\n else\n toAppend = formatter(params[i]);\n\n bytes += toAppend; \n });\n return bytes;\n};\n\nvar dynamicBytesLength = function (type) {\n if (arrayType(type) || type === 'string') // only string itself that is dynamic; stringX is static length.\n return c.ETH_PADDING * 2;\n return 0;\n};\n\nvar outputTypes = types.outputTypes(); \n\n/// Formats output bytes back to param list\n/// @param contract abi method outputs\n/// @param bytes representtion of output \n/// @returns array of output params \nvar formatOutput = function (outs, output) {\n \n output = output.slice(2);\n var result = [];\n var padding = c.ETH_PADDING * 2;\n\n var dynamicPartLength = outs.reduce(function (acc, curr) {\n return acc + dynamicBytesLength(curr.type);\n }, 0);\n \n var dynamicPart = output.slice(0, dynamicPartLength);\n output = output.slice(dynamicPartLength);\n\n outs.forEach(function (out, i) {\n /*jshint maxcomplexity:6 */\n var typeMatch = false;\n for (var j = 0; j < outputTypes.length && !typeMatch; j++) {\n typeMatch = outputTypes[j].type(outs[i].type);\n }\n\n if (!typeMatch) {\n displayTypeError(outs[i].type);\n }\n\n var formatter = outputTypes[j - 1].format;\n if (arrayType(outs[i].type)) {\n var size = f.formatOutputUInt(dynamicPart.slice(0, padding));\n dynamicPart = dynamicPart.slice(padding);\n var array = [];\n for (var k = 0; k < size; k++) {\n array.push(formatter(output.slice(0, padding))); \n output = output.slice(padding);\n }\n result.push(array);\n }\n else if (types.prefixedType('string')(outs[i].type)) {\n dynamicPart = dynamicPart.slice(padding); \n result.push(formatter(output.slice(0, padding)));\n output = output.slice(padding);\n } else {\n result.push(formatter(output.slice(0, padding)));\n output = output.slice(padding);\n }\n });\n\n return result;\n};\n\n/// @param json abi for contract\n/// @returns input parser object for given json abi\n/// TODO: refactor creating the parser, do not double logic from contract\nvar inputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n var displayName = utils.extractDisplayName(method.name); \n var typeName = utils.extractTypeName(method.name);\n\n var impl = function () {\n var params = Array.prototype.slice.call(arguments);\n return formatInput(method.inputs, params);\n };\n \n if (parser[displayName] === undefined) {\n parser[displayName] = impl;\n }\n\n parser[displayName][typeName] = impl;\n });\n\n return parser;\n};\n\n/// @param json abi for contract\n/// @returns output parser for given json abi\nvar outputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n\n var displayName = utils.extractDisplayName(method.name); \n var typeName = utils.extractTypeName(method.name);\n\n var impl = function (output) {\n return formatOutput(method.outputs, output);\n };\n\n if (parser[displayName] === undefined) {\n parser[displayName] = impl;\n }\n\n parser[displayName][typeName] = impl;\n });\n\n return parser;\n};\n\n/// @param function/event name for which we want to get signature\n/// @returns signature of function/event with given name\nvar signatureFromAscii = function (name) {\n return web3.sha3(web3.fromAscii(name)).slice(0, 2 + c.ETH_SIGNATURE_LENGTH * 2);\n};\n\nvar eventSignatureFromAscii = function (name) {\n return web3.sha3(web3.fromAscii(name));\n};\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n formatInput: formatInput,\n formatOutput: formatOutput,\n signatureFromAscii: signatureFromAscii,\n eventSignatureFromAscii: eventSignatureFromAscii\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 abi.js\n * @authors:\n * Marek Kotewicz \n * Gav Wood \n * @date 2014\n */\n\nvar utils = require('./utils');\nvar types = require('./types');\nvar c = require('./const');\nvar f = require('./formatters');\n\nvar displayTypeError = function (type) {\n console.error('parser does not support type: ' + type);\n};\n\n/// This method should be called if we want to check if givent type is an array type\n/// @returns true if it is, otherwise false\nvar arrayType = function (type) {\n return type.slice(-2) === '[]';\n};\n\nvar dynamicTypeBytes = function (type, value) {\n // TODO: decide what to do with array of strings\n if (arrayType(type) || type === 'string') // only string itself that is dynamic; stringX is static length.\n return f.formatInputInt(value.length);\n return \"\";\n};\n\nvar inputTypes = types.inputTypes();\n\n/// Formats input params to bytes\n/// @param abi contract method inputs\n/// @param array of params that will be formatted to bytes\n/// @returns bytes representation of input params\nvar formatInput = function (inputs, params) {\n var bytes = \"\";\n var toAppendConstant = \"\";\n var toAppendArrayContent = \"\";\n\n /// first we iterate in search for dynamic\n inputs.forEach(function (input, index) {\n bytes += dynamicTypeBytes(input.type, params[index]);\n });\n\n inputs.forEach(function (input, i) {\n /*jshint maxcomplexity:5 */\n var typeMatch = false;\n for (var j = 0; j < inputTypes.length && !typeMatch; j++) {\n typeMatch = inputTypes[j].type(inputs[i].type, params[i]);\n }\n if (!typeMatch) {\n displayTypeError(inputs[i].type);\n }\n\n var formatter = inputTypes[j - 1].format;\n\n if (arrayType(inputs[i].type))\n toAppendArrayContent += params[i].reduce(function (acc, curr) {\n return acc + formatter(curr);\n }, \"\");\n else if (inputs[i].type === 'string')\n toAppendArrayContent += formatter(params[i]);\n else\n toAppendConstant += formatter(params[i]);\n });\n\n bytes += toAppendConstant + toAppendArrayContent;\n\n return bytes;\n};\n\nvar dynamicBytesLength = function (type) {\n if (arrayType(type) || type === 'string') // only string itself that is dynamic; stringX is static length.\n return c.ETH_PADDING * 2;\n return 0;\n};\n\nvar outputTypes = types.outputTypes();\n\n/// Formats output bytes back to param list\n/// @param contract abi method outputs\n/// @param bytes representtion of output\n/// @returns array of output params\nvar formatOutput = function (outs, output) {\n\n output = output.slice(2);\n var result = [];\n var padding = c.ETH_PADDING * 2;\n\n var dynamicPartLength = outs.reduce(function (acc, curr) {\n return acc + dynamicBytesLength(curr.type);\n }, 0);\n\n var dynamicPart = output.slice(0, dynamicPartLength);\n output = output.slice(dynamicPartLength);\n\n outs.forEach(function (out, i) {\n /*jshint maxcomplexity:6 */\n var typeMatch = false;\n for (var j = 0; j < outputTypes.length && !typeMatch; j++) {\n typeMatch = outputTypes[j].type(outs[i].type);\n }\n\n if (!typeMatch) {\n displayTypeError(outs[i].type);\n }\n\n var formatter = outputTypes[j - 1].format;\n if (arrayType(outs[i].type)) {\n var size = f.formatOutputUInt(dynamicPart.slice(0, padding));\n dynamicPart = dynamicPart.slice(padding);\n var array = [];\n for (var k = 0; k < size; k++) {\n array.push(formatter(output.slice(0, padding)));\n output = output.slice(padding);\n }\n result.push(array);\n }\n else if (types.prefixedType('string')(outs[i].type)) {\n dynamicPart = dynamicPart.slice(padding);\n result.push(formatter(output.slice(0, padding)));\n output = output.slice(padding);\n } else {\n result.push(formatter(output.slice(0, padding)));\n output = output.slice(padding);\n }\n });\n\n return result;\n};\n\n/// @param json abi for contract\n/// @returns input parser object for given json abi\n/// TODO: refactor creating the parser, do not double logic from contract\nvar inputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n var displayName = utils.extractDisplayName(method.name);\n var typeName = utils.extractTypeName(method.name);\n\n var impl = function () {\n var params = Array.prototype.slice.call(arguments);\n return formatInput(method.inputs, params);\n };\n\n if (parser[displayName] === undefined) {\n parser[displayName] = impl;\n }\n\n parser[displayName][typeName] = impl;\n });\n\n return parser;\n};\n\n/// @param json abi for contract\n/// @returns output parser for given json abi\nvar outputParser = function (json) {\n var parser = {};\n json.forEach(function (method) {\n\n var displayName = utils.extractDisplayName(method.name);\n var typeName = utils.extractTypeName(method.name);\n\n var impl = function (output) {\n return formatOutput(method.outputs, output);\n };\n\n if (parser[displayName] === undefined) {\n parser[displayName] = impl;\n }\n\n parser[displayName][typeName] = impl;\n });\n\n return parser;\n};\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n formatInput: formatInput,\n formatOutput: formatOutput\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 const.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\n/// required to define ETH_BIGNUMBER_ROUNDING_MODE\nif (\"build\" !== 'build') {/*\n var BigNumber = require('bignumber.js'); // jshint ignore:line\n*/}\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};\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 contract.js\n * @authors:\n * Marek Kotewicz \n * @date 2014\n */\n\nvar web3 = require('./web3'); \nvar abi = require('./abi');\nvar utils = require('./utils');\nvar eventImpl = require('./event');\n\nvar exportNatspecGlobals = function (vars) {\n // it's used byt natspec.js\n // TODO: figure out better way to solve this\n web3._currentContractAbi = vars.abi;\n web3._currentContractAddress = vars.address;\n web3._currentContractMethodName = vars.method;\n web3._currentContractMethodParams = vars.params;\n};\n\nvar addFunctionRelatedPropertiesToContract = function (contract) {\n \n contract.call = function (options) {\n contract._isTransact = false;\n contract._options = options;\n return contract;\n };\n\n contract.transact = function (options) {\n contract._isTransact = true;\n contract._options = options;\n return contract;\n };\n\n contract._options = {};\n ['gas', 'gasPrice', 'value', 'from'].forEach(function(p) {\n contract[p] = function (v) {\n contract._options[p] = v;\n return contract;\n };\n });\n\n};\n\nvar addFunctionsToContract = function (contract, desc, address) {\n var inputParser = abi.inputParser(desc);\n var outputParser = abi.outputParser(desc);\n\n // create contract functions\n utils.filterFunctions(desc).forEach(function (method) {\n\n var displayName = utils.extractDisplayName(method.name);\n var typeName = utils.extractTypeName(method.name);\n\n var impl = function () {\n /*jshint maxcomplexity:7 */\n var params = Array.prototype.slice.call(arguments);\n var signature = abi.signatureFromAscii(method.name);\n var parsed = inputParser[displayName][typeName].apply(null, params);\n\n var options = contract._options || {};\n options.to = address;\n options.data = signature + parsed;\n \n var isTransact = contract._isTransact === true || (contract._isTransact !== false && !method.constant);\n var collapse = options.collapse !== false;\n \n // reset\n contract._options = {};\n contract._isTransact = null;\n\n if (isTransact) {\n \n exportNatspecGlobals({\n abi: desc,\n address: address,\n method: method.name,\n params: params\n });\n\n // transactions do not have any output, cause we do not know, when they will be processed\n web3.eth.transact(options);\n return;\n }\n \n var output = web3.eth.call(options);\n var ret = outputParser[displayName][typeName](output);\n if (collapse)\n {\n if (ret.length === 1)\n ret = ret[0];\n else if (ret.length === 0)\n ret = null;\n }\n return ret;\n };\n\n if (contract[displayName] === undefined) {\n contract[displayName] = impl;\n }\n\n contract[displayName][typeName] = impl;\n });\n};\n\nvar addEventRelatedPropertiesToContract = function (contract, desc, address) {\n contract.address = address;\n contract._onWatchEventResult = function (data) {\n var matchingEvent = event.getMatchingEvent(utils.filterEvents(desc));\n var parser = eventImpl.outputParser(matchingEvent);\n return parser(data);\n };\n \n Object.defineProperty(contract, 'topic', {\n get: function() {\n return utils.filterEvents(desc).map(function (e) {\n return abi.eventSignatureFromAscii(e.name);\n });\n }\n });\n\n};\n\nvar addEventsToContract = function (contract, desc, address) {\n // create contract events\n utils.filterEvents(desc).forEach(function (e) {\n\n var impl = function () {\n var params = Array.prototype.slice.call(arguments);\n var signature = abi.eventSignatureFromAscii(e.name);\n var event = eventImpl.inputParser(address, signature, e);\n var o = event.apply(null, params);\n var outputFormatter = function (data) {\n var parser = eventImpl.outputParser(e);\n return parser(data);\n };\n return web3.eth.watch(o, undefined, undefined, outputFormatter);\n };\n \n // this property should be used by eth.filter to check if object is an event\n impl._isEvent = true;\n\n var displayName = utils.extractDisplayName(e.name);\n var typeName = utils.extractTypeName(e.name);\n\n if (contract[displayName] === undefined) {\n contract[displayName] = impl;\n }\n\n contract[displayName][typeName] = impl;\n\n });\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('0x0123123121', abi); // creation of contract object\n *\n * myContract.myMethod('this is test string param for call'); // myMethod call (implicit, default)\n * myContract.call().myMethod('this is test string param for call'); // myMethod call (explicit)\n * myContract.transact().myMethod('this is test string param for transact'); // myMethod transact\n *\n * @param address - address of the contract, which should be called\n * @param desc - abi json description of the contract, which is being created\n * @returns contract object\n */\n\nvar contract = function (address, desc) {\n\n // workaround for invalid assumption that method.name is the full anonymous prototype of the method.\n // it's not. it's just the name. the rest of the code assumes it's actually the anonymous\n // prototype, so we make it so as a workaround.\n // TODO: we may not want to modify input params, maybe use copy instead?\n desc.forEach(function (method) {\n if (method.name.indexOf('(') === -1) {\n var displayName = method.name;\n var typeName = method.inputs.map(function(i){return i.type; }).join();\n method.name = displayName + '(' + typeName + ')';\n }\n });\n\n var result = {};\n addFunctionRelatedPropertiesToContract(result);\n addFunctionsToContract(result, desc, address);\n addEventRelatedPropertiesToContract(result, desc, address);\n addEventsToContract(result, desc, address);\n\n return result;\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 contract.js\n * @authors:\n * Marek Kotewicz \n * @date 2014\n */\n\nvar web3 = require('./web3'); \nvar abi = require('./abi');\nvar utils = require('./utils');\nvar eventImpl = require('./event');\nvar signature = require('./signature');\n\nvar exportNatspecGlobals = function (vars) {\n // it's used byt natspec.js\n // TODO: figure out better way to solve this\n web3._currentContractAbi = vars.abi;\n web3._currentContractAddress = vars.address;\n web3._currentContractMethodName = vars.method;\n web3._currentContractMethodParams = vars.params;\n};\n\nvar addFunctionRelatedPropertiesToContract = function (contract) {\n \n contract.call = function (options) {\n contract._isTransact = false;\n contract._options = options;\n return contract;\n };\n\n contract.transact = function (options) {\n contract._isTransact = true;\n contract._options = options;\n return contract;\n };\n\n contract._options = {};\n ['gas', 'gasPrice', 'value', 'from'].forEach(function(p) {\n contract[p] = function (v) {\n contract._options[p] = v;\n return contract;\n };\n });\n\n};\n\nvar addFunctionsToContract = function (contract, desc, address) {\n var inputParser = abi.inputParser(desc);\n var outputParser = abi.outputParser(desc);\n\n // create contract functions\n utils.filterFunctions(desc).forEach(function (method) {\n\n var displayName = utils.extractDisplayName(method.name);\n var typeName = utils.extractTypeName(method.name);\n\n var impl = function () {\n /*jshint maxcomplexity:7 */\n var params = Array.prototype.slice.call(arguments);\n var sign = signature.functionSignatureFromAscii(method.name);\n var parsed = inputParser[displayName][typeName].apply(null, params);\n\n var options = contract._options || {};\n options.to = address;\n options.data = sign + parsed;\n \n var isTransact = contract._isTransact === true || (contract._isTransact !== false && !method.constant);\n var collapse = options.collapse !== false;\n \n // reset\n contract._options = {};\n contract._isTransact = null;\n\n if (isTransact) {\n \n exportNatspecGlobals({\n abi: desc,\n address: address,\n method: method.name,\n params: params\n });\n\n // transactions do not have any output, cause we do not know, when they will be processed\n web3.eth.transact(options);\n return;\n }\n \n var output = web3.eth.call(options);\n var ret = outputParser[displayName][typeName](output);\n if (collapse)\n {\n if (ret.length === 1)\n ret = ret[0];\n else if (ret.length === 0)\n ret = null;\n }\n return ret;\n };\n\n if (contract[displayName] === undefined) {\n contract[displayName] = impl;\n }\n\n contract[displayName][typeName] = impl;\n });\n};\n\nvar addEventRelatedPropertiesToContract = function (contract, desc, address) {\n contract.address = address;\n contract._onWatchEventResult = function (data) {\n var matchingEvent = event.getMatchingEvent(utils.filterEvents(desc));\n var parser = eventImpl.outputParser(matchingEvent);\n return parser(data);\n };\n \n Object.defineProperty(contract, 'topic', {\n get: function() {\n return utils.filterEvents(desc).map(function (e) {\n return signature.eventSignatureFromAscii(e.name);\n });\n }\n });\n\n};\n\nvar addEventsToContract = function (contract, desc, address) {\n // create contract events\n utils.filterEvents(desc).forEach(function (e) {\n\n var impl = function () {\n var params = Array.prototype.slice.call(arguments);\n var sign = signature.eventSignatureFromAscii(e.name);\n var event = eventImpl.inputParser(address, sign, e);\n var o = event.apply(null, params);\n var outputFormatter = function (data) {\n var parser = eventImpl.outputParser(e);\n return parser(data);\n };\n return web3.eth.watch(o, undefined, undefined, outputFormatter);\n };\n \n // this property should be used by eth.filter to check if object is an event\n impl._isEvent = true;\n\n var displayName = utils.extractDisplayName(e.name);\n var typeName = utils.extractTypeName(e.name);\n\n if (contract[displayName] === undefined) {\n contract[displayName] = impl;\n }\n\n contract[displayName][typeName] = impl;\n\n });\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('0x0123123121', abi); // creation of contract object\n *\n * myContract.myMethod('this is test string param for call'); // myMethod call (implicit, default)\n * myContract.call().myMethod('this is test string param for call'); // myMethod call (explicit)\n * myContract.transact().myMethod('this is test string param for transact'); // myMethod transact\n *\n * @param address - address of the contract, which should be called\n * @param desc - abi json description of the contract, which is being created\n * @returns contract object\n */\n\nvar contract = function (address, desc) {\n\n // workaround for invalid assumption that method.name is the full anonymous prototype of the method.\n // it's not. it's just the name. the rest of the code assumes it's actually the anonymous\n // prototype, so we make it so as a workaround.\n // TODO: we may not want to modify input params, maybe use copy instead?\n desc.forEach(function (method) {\n if (method.name.indexOf('(') === -1) {\n var displayName = method.name;\n var typeName = method.inputs.map(function(i){return i.type; }).join();\n method.name = displayName + '(' + typeName + ')';\n }\n });\n\n var result = {};\n addFunctionRelatedPropertiesToContract(result);\n addFunctionsToContract(result, desc, address);\n addEventRelatedPropertiesToContract(result, desc, address);\n addEventsToContract(result, desc, address);\n\n return result;\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\n/// @returns an array of objects describing web3.db api methods\nvar methods = function () {\n return [\n { name: 'put', call: 'db_put' },\n { name: 'get', call: 'db_get' },\n { name: 'putString', call: 'db_putString' },\n { name: 'getString', call: 'db_getString' }\n ];\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/** @file eth.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\n/// @returns an array of objects describing web3.eth api methods\nvar methods = function () {\n var blockCall = function (args) {\n return typeof args[0] === \"string\" ? \"eth_blockByHash\" : \"eth_blockByNumber\";\n };\n\n var transactionCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_transactionByHash' : 'eth_transactionByNumber';\n };\n\n var uncleCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_uncleByHash' : 'eth_uncleByNumber';\n };\n\n var transactionCountCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_transactionCountByHash' : 'eth_transactionCountByNumber';\n };\n\n var uncleCountCall = function (args) {\n return typeof args[0] === \"string\" ? 'eth_uncleCountByHash' : 'eth_uncleCountByNumber';\n };\n\n return [\n { name: 'balanceAt', call: 'eth_balanceAt' },\n { name: 'stateAt', call: 'eth_stateAt' },\n { name: 'storageAt', call: 'eth_storageAt' },\n { name: 'countAt', call: 'eth_countAt'},\n { name: 'codeAt', call: 'eth_codeAt' },\n { name: 'transact', call: 'eth_transact' },\n { name: 'call', call: 'eth_call' },\n { name: 'block', call: blockCall },\n { name: 'transaction', call: transactionCall },\n { name: 'uncle', call: uncleCall },\n { name: 'compilers', call: 'eth_compilers' },\n { name: 'flush', call: 'eth_flush' },\n { name: 'lll', call: 'eth_lll' },\n { name: 'solidity', call: 'eth_solidity' },\n { name: 'serpent', call: 'eth_serpent' },\n { name: 'logs', call: 'eth_logs' },\n { name: 'transactionCount', call: transactionCountCall },\n { name: 'uncleCount', call: uncleCountCall }\n ];\n};\n\n/// @returns an array of objects describing web3.eth api properties\nvar properties = function () {\n return [\n { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' },\n { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' },\n { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' },\n { name: 'gasPrice', getter: 'eth_gasPrice' },\n { name: 'accounts', getter: 'eth_accounts' },\n { name: 'peerCount', getter: 'eth_peerCount' },\n { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' },\n { name: 'number', getter: 'eth_number'}\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/** @file event.js\n * @authors:\n * Marek Kotewicz \n * @date 2014\n */\n\nvar abi = require('./abi');\nvar utils = require('./utils');\n\n/// filter inputs array && returns only indexed (or not) inputs\n/// @param inputs array\n/// @param bool if result should be an array of indexed params on not\n/// @returns array of (not?) indexed params\nvar filterInputs = function (inputs, indexed) {\n return inputs.filter(function (current) {\n return current.indexed === indexed;\n });\n};\n\nvar inputWithName = function (inputs, name) {\n var index = utils.findIndex(inputs, function (input) {\n return input.name === name;\n });\n \n if (index === -1) {\n console.error('indexed param with name ' + name + ' not found');\n return undefined;\n }\n return inputs[index];\n};\n\nvar indexedParamsToTopics = function (event, indexed) {\n // sort keys?\n return Object.keys(indexed).map(function (key) {\n var inputs = [inputWithName(filterInputs(event.inputs, true), key)];\n\n var value = indexed[key];\n if (value instanceof Array) {\n return value.map(function (v) {\n return abi.formatInput(inputs, [v]);\n }); \n }\n return abi.formatInput(inputs, [value]);\n });\n};\n\nvar inputParser = function (address, signature, event) {\n \n // valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.watch'\n return function (indexed, options) {\n var o = options || {};\n o.address = address;\n o.topic = [];\n o.topic.push(signature);\n if (indexed) {\n o.topic = o.topic.concat(indexedParamsToTopics(event, indexed));\n }\n return o;\n };\n};\n\nvar getArgumentsObject = function (inputs, indexed, notIndexed) {\n var indexedCopy = indexed.slice();\n var notIndexedCopy = notIndexed.slice();\n return inputs.reduce(function (acc, current) {\n var value;\n if (current.indexed)\n value = indexedCopy.splice(0, 1)[0];\n else\n value = notIndexedCopy.splice(0, 1)[0];\n\n acc[current.name] = value;\n return acc;\n }, {}); \n};\n \nvar outputParser = function (event) {\n \n return function (output) {\n var result = {\n event: utils.extractDisplayName(event.name),\n number: output.number,\n args: {}\n };\n\n output.topics = output.topic; // fallback for go-ethereum\n if (!output.topic) {\n return result;\n }\n \n var indexedOutputs = filterInputs(event.inputs, true);\n var indexedData = \"0x\" + output.topic.slice(1, output.topic.length).map(function (topic) { return topic.slice(2); }).join(\"\");\n var indexedRes = abi.formatOutput(indexedOutputs, indexedData);\n\n var notIndexedOutputs = filterInputs(event.inputs, false);\n var notIndexedRes = abi.formatOutput(notIndexedOutputs, output.data);\n\n result.args = getArgumentsObject(event.inputs, indexedRes, notIndexedRes);\n\n return result;\n };\n};\n\nvar getMatchingEvent = function (events, payload) {\n for (var i = 0; i < events.length; i++) {\n var signature = abi.eventSignatureFromAscii(events[i].name); \n if (signature === payload.topic[0]) {\n return events[i];\n }\n }\n return undefined;\n};\n\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n getMatchingEvent: getMatchingEvent\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 event.js\n * @authors:\n * Marek Kotewicz \n * @date 2014\n */\n\nvar abi = require('./abi');\nvar utils = require('./utils');\nvar signature = require('./signature');\n\n/// filter inputs array && returns only indexed (or not) inputs\n/// @param inputs array\n/// @param bool if result should be an array of indexed params on not\n/// @returns array of (not?) indexed params\nvar filterInputs = function (inputs, indexed) {\n return inputs.filter(function (current) {\n return current.indexed === indexed;\n });\n};\n\nvar inputWithName = function (inputs, name) {\n var index = utils.findIndex(inputs, function (input) {\n return input.name === name;\n });\n \n if (index === -1) {\n console.error('indexed param with name ' + name + ' not found');\n return undefined;\n }\n return inputs[index];\n};\n\nvar indexedParamsToTopics = function (event, indexed) {\n // sort keys?\n return Object.keys(indexed).map(function (key) {\n var inputs = [inputWithName(filterInputs(event.inputs, true), key)];\n\n var value = indexed[key];\n if (value instanceof Array) {\n return value.map(function (v) {\n return abi.formatInput(inputs, [v]);\n }); \n }\n return abi.formatInput(inputs, [value]);\n });\n};\n\nvar inputParser = function (address, sign, event) {\n \n // valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.watch'\n return function (indexed, options) {\n var o = options || {};\n o.address = address;\n o.topic = [];\n o.topic.push(sign);\n if (indexed) {\n o.topic = o.topic.concat(indexedParamsToTopics(event, indexed));\n }\n return o;\n };\n};\n\nvar getArgumentsObject = function (inputs, indexed, notIndexed) {\n var indexedCopy = indexed.slice();\n var notIndexedCopy = notIndexed.slice();\n return inputs.reduce(function (acc, current) {\n var value;\n if (current.indexed)\n value = indexedCopy.splice(0, 1)[0];\n else\n value = notIndexedCopy.splice(0, 1)[0];\n\n acc[current.name] = value;\n return acc;\n }, {}); \n};\n \nvar outputParser = function (event) {\n \n return function (output) {\n var result = {\n event: utils.extractDisplayName(event.name),\n number: output.number,\n hash: output.hash,\n args: {}\n };\n\n output.topics = output.topic; // fallback for go-ethereum\n if (!output.topic) {\n return result;\n }\n \n var indexedOutputs = filterInputs(event.inputs, true);\n var indexedData = \"0x\" + output.topic.slice(1, output.topic.length).map(function (topic) { return topic.slice(2); }).join(\"\");\n var indexedRes = abi.formatOutput(indexedOutputs, indexedData);\n\n var notIndexedOutputs = filterInputs(event.inputs, false);\n var notIndexedRes = abi.formatOutput(notIndexedOutputs, output.data);\n\n result.args = getArgumentsObject(event.inputs, indexedRes, notIndexedRes);\n\n return result;\n };\n};\n\nvar getMatchingEvent = function (events, payload) {\n for (var i = 0; i < events.length; i++) {\n var sign = signature.eventSignatureFromAscii(events[i].name); \n if (sign === payload.topic[0]) {\n return events[i];\n }\n }\n return undefined;\n};\n\n\nmodule.exports = {\n inputParser: inputParser,\n outputParser: outputParser,\n getMatchingEvent: getMatchingEvent\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 filter.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Gav Wood \n * @date 2014\n */\n\n/// Should be called to check if filter implementation is valid\n/// @returns true if it is, otherwise false\nvar implementationIsValid = function (i) {\n return !!i && \n typeof i.newFilter === 'function' && \n typeof i.getMessages === 'function' && \n typeof i.uninstallFilter === 'function' &&\n typeof i.startPolling === 'function' &&\n typeof i.stopPolling === 'function';\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 if (typeof options === 'string') {\n return options;\n } \n\n options = options || {};\n\n if (options.topics) {\n console.warn('\"topics\" is deprecated, is \"topic\" instead');\n }\n\n // evaluate lazy properties\n return {\n to: options.to,\n topic: options.topic,\n earliest: options.earliest,\n latest: options.latest,\n max: options.max,\n skip: options.skip,\n address: options.address\n };\n};\n\n/// Should be used when we want to watch something\n/// it's using inner polling mechanism and is notified about changes\n/// @param options are filter options\n/// @param implementation, an abstract polling implementation\n/// @param formatter (optional), callback function which formats output before 'real' callback \nvar filter = function(options, implementation, formatter) {\n if (!implementationIsValid(implementation)) {\n console.error('filter implemenation is invalid');\n return;\n }\n\n options = getOptions(options);\n var callbacks = [];\n var filterId = implementation.newFilter(options);\n var onMessages = function (messages) {\n messages.forEach(function (message) {\n message = formatter ? formatter(message) : message;\n callbacks.forEach(function (callback) {\n callback(message);\n });\n });\n };\n\n implementation.startPolling(filterId, onMessages, implementation.uninstallFilter);\n\n var changed = function (callback) {\n callbacks.push(callback);\n };\n\n var messages = function () {\n return implementation.getMessages(filterId);\n };\n \n var uninstall = function () {\n implementation.stopPolling(filterId);\n implementation.uninstallFilter(filterId);\n callbacks = [];\n };\n\n return {\n changed: changed,\n arrived: changed,\n happened: changed,\n messages: messages,\n logs: messages,\n uninstall: uninstall\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/** @file formatters.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nif (\"build\" !== 'build') {/*\n var BigNumber = require('bignumber.js'); // jshint ignore:line\n*/}\n\nvar utils = require('./utils');\nvar c = require('./const');\n\n/// @param string string to be padded\n/// @param number of characters that result string should have\n/// @param sign, by default 0\n/// @returns right aligned string\nvar padLeft = function (string, chars, sign) {\n return new Array(chars - string.length + 1).join(sign ? sign : \"0\") + string;\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/// @returns right-aligned byte representation of int\nvar formatInputInt = function (value) {\n /*jshint maxcomplexity:7 */\n var padding = c.ETH_PADDING * 2;\n if (value instanceof BigNumber || typeof value === 'number') {\n if (typeof value === 'number')\n value = new BigNumber(value);\n BigNumber.config(c.ETH_BIGNUMBER_ROUNDING_MODE);\n value = value.round();\n\n if (value.lessThan(0)) \n value = new BigNumber(\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\", 16).plus(value).plus(1);\n value = value.toString(16);\n }\n else if (value.indexOf('0x') === 0)\n value = value.substr(2);\n else if (typeof value === 'string')\n value = formatInputInt(new BigNumber(value));\n else\n value = (+value).toString(16);\n return padLeft(value, padding);\n};\n\n/// Formats input value to byte representation of string\n/// @returns left-algined byte representation of string\nvar formatInputString = function (value) {\n return utils.fromAscii(value, c.ETH_PADDING).substr(2);\n};\n\n/// Formats input value to byte representation of bool\n/// @returns right-aligned byte representation bool\nvar formatInputBool = function (value) {\n return '000000000000000000000000000000000000000000000000000000000000000' + (value ? '1' : '0');\n};\n\n/// Formats input value to byte representation of real\n/// Values are multiplied by 2^m and encoded as integers\n/// @returns byte representation of real\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/// @param value is hex format\n/// @returns true if it is negative, otherwise false\nvar signedIsNegative = function (value) {\n return (new BigNumber(value.substr(0, 1), 16).toString(2).substr(0, 1)) === '1';\n};\n\n/// Formats input right-aligned input bytes to int\n/// @returns right-aligned input bytes formatted to int\nvar formatOutputInt = function (value) {\n value = value || \"0\";\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/// Formats big right-aligned input bytes to uint\n/// @returns right-aligned input bytes formatted to uint\nvar formatOutputUInt = function (value) {\n value = value || \"0\";\n return new BigNumber(value, 16);\n};\n\n/// @returns input bytes formatted to real\nvar formatOutputReal = function (value) {\n return formatOutputInt(value).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/// @returns input bytes formatted to ureal\nvar formatOutputUReal = function (value) {\n return formatOutputUInt(value).dividedBy(new BigNumber(2).pow(128)); \n};\n\n/// @returns right-aligned input bytes formatted to hex\nvar formatOutputHash = function (value) {\n return \"0x\" + value;\n};\n\n/// @returns right-aligned input bytes formatted to bool\nvar formatOutputBool = function (value) {\n return value === '0000000000000000000000000000000000000000000000000000000000000001' ? true : false;\n};\n\n/// @returns left-aligned input bytes formatted to ascii string\nvar formatOutputString = function (value) {\n return utils.toAscii(value);\n};\n\n/// @returns right-aligned input bytes formatted to address\nvar formatOutputAddress = function (value) {\n return \"0x\" + value.slice(value.length - 40, value.length);\n};\n\n\nmodule.exports = {\n formatInputInt: formatInputInt,\n formatInputString: formatInputString,\n formatInputBool: formatInputBool,\n formatInputReal: formatInputReal,\n formatOutputInt: formatOutputInt,\n formatOutputUInt: formatOutputUInt,\n formatOutputReal: formatOutputReal,\n formatOutputUReal: formatOutputUReal,\n formatOutputHash: formatOutputHash,\n formatOutputBool: formatOutputBool,\n formatOutputString: formatOutputString,\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/** @file httpsync.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\nif (\"build\" !== 'build') {/*\n var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\n*/}\n\nvar HttpSyncProvider = function (host) {\n this.handlers = [];\n this.host = host || 'http://localhost:8080';\n};\n\nHttpSyncProvider.prototype.send = function (payload) {\n //var data = formatJsonRpcObject(payload);\n\n var request = new XMLHttpRequest();\n request.open('POST', this.host, false);\n request.send(JSON.stringify(payload));\n\n var result = request.responseText;\n // check request.status\n if(request.status !== 200)\n return;\n return JSON.parse(result);\n};\n\nmodule.exports = HttpSyncProvider;\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 httpsync.js\n * @authors:\n * Marek Kotewicz \n * Marian Oancea \n * @date 2014\n */\n\nif (\"build\" !== 'build') {/*\n var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line\n*/}\n\nvar HttpSyncProvider = function (host) {\n this.handlers = [];\n this.host = host || 'http://127.0.0.1:8080';\n};\n\nHttpSyncProvider.prototype.send = function (payload) {\n //var data = formatJsonRpcObject(payload);\n\n var request = new XMLHttpRequest();\n request.open('POST', this.host, false);\n request.send(JSON.stringify(payload));\n\n var result = request.responseText;\n // check request.status\n if(request.status !== 200)\n return;\n return JSON.parse(result);\n};\n\nmodule.exports = HttpSyncProvider;\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 messageId = 1;\n\n/// Should be called to valid json create payload object\n/// @param method of jsonrpc call, required\n/// @param params, an array of method params, optional\n/// @returns valid jsonrpc payload object\nvar 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: messageId++\n }; \n};\n\n/// Should be called to check if jsonrpc response is valid\n/// @returns true if response is valid, otherwise false \nvar 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/// Should be called to create batch payload object\n/// @param messages, an array of objects with method (required) and params (optional) fields\nvar toBatchPayload = function (messages) {\n return messages.map(function (message) {\n return toPayload(message.method, message.params);\n }); \n};\n\nmodule.exports = {\n toPayload: toPayload,\n isValidResponse: isValidResponse,\n toBatchPayload: toBatchPayload\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/** @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/** @file requestmanager.js\n * @authors:\n * Jeffrey Wilcke \n * Marek Kotewicz \n * Marian Oancea \n * Gav Wood \n * @date 2014\n */\n\nvar jsonrpc = require('./jsonrpc');\nvar c = require('./const');\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 */\nvar requestManager = function() {\n var polls = [];\n var timeout = null;\n var provider;\n\n var send = function (data) {\n var payload = jsonrpc.toPayload(data.method, data.params);\n \n if (!provider) {\n console.error('provider is not set');\n return null;\n }\n\n var result = provider.send(payload);\n\n if (!jsonrpc.isValidResponse(result)) {\n console.log(result);\n return null;\n }\n \n return result.result;\n };\n\n var setProvider = function (p) {\n provider = p;\n };\n\n /*jshint maxparams:4 */\n var startPolling = function (data, pollId, callback, uninstall) {\n polls.push({data: data, id: pollId, callback: callback, uninstall: uninstall});\n };\n /*jshint maxparams:3 */\n\n var stopPolling = function (pollId) {\n for (var i = polls.length; i--;) {\n var poll = polls[i];\n if (poll.id === pollId) {\n polls.splice(i, 1);\n }\n }\n };\n\n var reset = function () {\n polls.forEach(function (poll) {\n poll.uninstall(poll.id); \n });\n polls = [];\n\n if (timeout) {\n clearTimeout(timeout);\n timeout = null;\n }\n poll();\n };\n\n var poll = function () {\n polls.forEach(function (data) {\n var result = send(data.data);\n if (!(result instanceof Array) || result.length === 0) {\n return;\n }\n data.callback(result);\n });\n timeout = setTimeout(poll, c.ETH_POLLING_TIMEOUT);\n };\n \n poll();\n\n return {\n send: send,\n setProvider: setProvider,\n startPolling: startPolling,\n stopPolling: stopPolling,\n reset: reset\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\n/// @returns an array of objects describing web3.shh api methods\nvar methods = function () {\n return [\n { name: 'post', call: 'shh_post' },\n { name: 'newIdentity', call: 'shh_newIdentity' },\n { name: 'haveIdentity', call: 'shh_haveIdentity' },\n { name: 'newGroup', call: 'shh_newGroup' },\n { name: 'addToGroup', call: 'shh_addToGroup' }\n ];\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 signature.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar web3 = require('./web3'); \nvar c = require('./const');\n\n/// @param function name for which we want to get signature\n/// @returns signature of function with given name\nvar functionSignatureFromAscii = function (name) {\n return web3.sha3(web3.fromAscii(name)).slice(0, 2 + c.ETH_SIGNATURE_LENGTH * 2);\n};\n\n/// @param event name for which we want to get signature\n/// @returns signature of event with given name\nvar eventSignatureFromAscii = function (name) {\n return web3.sha3(web3.fromAscii(name));\n};\n\nmodule.exports = {\n functionSignatureFromAscii: functionSignatureFromAscii,\n eventSignatureFromAscii: eventSignatureFromAscii\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 types.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar f = require('./formatters');\n\n/// @param expected type prefix (string)\n/// @returns function which checks if type has matching prefix. if yes, returns true, otherwise false\nvar prefixedType = function (prefix) {\n return function (type) {\n return type.indexOf(prefix) === 0;\n };\n};\n\n/// @param expected type name (string)\n/// @returns function which checks if type is matching expected one. if yes, returns true, otherwise false\nvar namedType = function (name) {\n return function (type) {\n return name === type;\n };\n};\n\n/// Setups input formatters for solidity types\n/// @returns an array of input formatters \nvar inputTypes = function () {\n \n return [\n { type: prefixedType('uint'), format: f.formatInputInt },\n { type: prefixedType('int'), format: f.formatInputInt },\n { type: prefixedType('hash'), format: f.formatInputInt },\n { type: prefixedType('string'), format: f.formatInputString }, \n { type: prefixedType('real'), format: f.formatInputReal },\n { type: prefixedType('ureal'), format: f.formatInputReal },\n { type: namedType('address'), format: f.formatInputInt },\n { type: namedType('bool'), format: f.formatInputBool }\n ];\n};\n\n/// Setups output formaters for solidity types\n/// @returns an array of output formatters\nvar outputTypes = function () {\n\n return [\n { type: prefixedType('uint'), format: f.formatOutputUInt },\n { type: prefixedType('int'), format: f.formatOutputInt },\n { type: prefixedType('hash'), format: f.formatOutputHash },\n { type: prefixedType('string'), format: f.formatOutputString },\n { type: prefixedType('real'), format: f.formatOutputReal },\n { type: prefixedType('ureal'), format: f.formatOutputUReal },\n { type: namedType('address'), format: f.formatOutputAddress },\n { type: namedType('bool'), format: f.formatOutputBool }\n ];\n};\n\nmodule.exports = {\n prefixedType: prefixedType,\n namedType: namedType,\n inputTypes: inputTypes,\n outputTypes: outputTypes\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 utils.js\n * @authors:\n * Marek Kotewicz \n * @date 2015\n */\n\nvar c = require('./const');\n\n/// Finds first index of array element matching pattern\n/// @param array\n/// @param callback pattern\n/// @returns index of element\nvar findIndex = function (array, callback) {\n var end = false;\n var i = 0;\n for (; i < array.length && !end; i++) {\n end = callback(array[i]);\n }\n return end ? i - 1 : -1;\n};\n\n/// @returns ascii string representation of hex value prefixed with 0x\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 \nvar toHex = 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/// @returns hex representation (prefixed by 0x) of ascii string\nvar fromAscii = function(str, pad) {\n pad = pad === undefined ? 0 : pad;\n var hex = toHex(str);\n while (hex.length < pad*2)\n hex += \"00\";\n return \"0x\" + hex;\n};\n\n/// @returns display name for function/event eg. multiply(uint256) -> multiply\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/// Filters all function from input abi\n/// @returns abi array with filtered objects of type 'function'\nvar filterFunctions = function (json) {\n return json.filter(function (current) {\n return current.type === 'function'; \n }); \n};\n\n/// Filters all events form input abi\n/// @returns abi array with filtered objects of type 'event'\nvar filterEvents = function (json) {\n return json.filter(function (current) {\n return current.type === 'event';\n });\n};\n\n/// used to transform value/string to eth string\n/// TODO: use BigNumber.js to parse int\n/// TODO: add tests for it!\nvar toEth = function (str) {\n /*jshint maxcomplexity:7 */\n var val = typeof str === \"string\" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str;\n var unit = 0;\n var units = c.ETH_UNITS;\n while (val > 3000 && unit < units.length - 1)\n {\n val /= 1000;\n unit++;\n }\n var s = val.toString().length < val.toFixed(2).length ? val.toString() : val.toFixed(2);\n var replaceFunction = function($0, $1, $2) {\n return $1 + ',' + $2;\n };\n\n while (true) {\n var o = s;\n s = s.replace(/(\\d)(\\d\\d\\d[\\.\\,])/, replaceFunction);\n if (o === s)\n break;\n }\n return s + ' ' + units[unit];\n};\n\nmodule.exports = {\n findIndex: findIndex,\n toAscii: toAscii,\n fromAscii: fromAscii,\n extractDisplayName: extractDisplayName,\n extractTypeName: extractTypeName,\n filterFunctions: filterFunctions,\n filterEvents: filterEvents,\n toEth: toEth\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\n/// @returns an array of objects describing web3.eth.watch api methods\nvar eth = function () {\n var newFilter = function (args) {\n return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter';\n };\n\n return [\n { name: 'newFilter', call: newFilter },\n { name: 'uninstallFilter', call: 'eth_uninstallFilter' },\n { name: 'getMessages', call: 'eth_filterLogs' }\n ];\n};\n\n/// @returns an array of objects describing web3.shh.watch api methods\nvar shh = function () {\n return [\n { name: 'newFilter', call: 'shh_newFilter' },\n { name: 'uninstallFilter', call: 'shh_uninstallFilter' },\n { name: 'getMessages', call: 'shh_getMessages' }\n ];\n};\n\nmodule.exports = {\n eth: eth,\n shh: shh\n};\n\n", diff --git a/dist/ethereum.min.js b/dist/ethereum.min.js index 88ad680c4..373a4aba4 100644 --- a/dist/ethereum.min.js +++ b/dist/ethereum.min.js @@ -1 +1 @@ -require=function t(n,e,r){function o(i,u){if(!e[i]){if(!n[i]){var f="function"==typeof require&&require;if(!u&&f)return f(i,!0);if(a)return a(i,!0);var s=new Error("Cannot find module '"+i+"'");throw s.code="MODULE_NOT_FOUND",s}var c=e[i]={exports:{}};n[i][0].call(c.exports,function(t){var e=n[i][1][t];return o(e?e:t)},c,c.exports,t,n,e,r)}return e[i].exports}for(var a="function"==typeof require&&require,i=0;iv;v++)g.push(h(n.slice(0,r))),n=n.slice(r);e.push(g)}else o.prefixedType("string")(t[s].type)?(c=c.slice(r),e.push(h(n.slice(0,r))),n=n.slice(r)):(e.push(h(n.slice(0,r))),n=n.slice(r))}),e},d=function(t){var n={};return t.forEach(function(t){var e=r.extractDisplayName(t.name),o=r.extractTypeName(t.name),a=function(){var n=Array.prototype.slice.call(arguments);return l(t.inputs,n)};void 0===n[e]&&(n[e]=a),n[e][o]=a}),n},g=function(t){var n={};return t.forEach(function(t){var e=r.extractDisplayName(t.name),o=r.extractTypeName(t.name),a=function(n){return h(t.outputs,n)};void 0===n[e]&&(n[e]=a),n[e][o]=a}),n},v=function(t){return e.sha3(e.fromAscii(t)).slice(0,2+2*a.ETH_SIGNATURE_LENGTH)},y=function(t){return e.sha3(e.fromAscii(t))};n.exports={inputParser:d,outputParser:g,formatInput:l,formatOutput:h,signatureFromAscii:v,eventSignatureFromAscii:y}},{"./const":2,"./formatters":8,"./types":14,"./utils":15,"./web3":17}],2:[function(t,n){var e=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];n.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:e,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:BigNumber.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3}},{}],3:[function(t,n){var e=t("./web3"),r=t("./abi"),o=t("./utils"),a=t("./event"),i=function(t){e._currentContractAbi=t.abi,e._currentContractAddress=t.address,e._currentContractMethodName=t.method,e._currentContractMethodParams=t.params},u=function(t){t.call=function(n){return t._isTransact=!1,t._options=n,t},t.transact=function(n){return t._isTransact=!0,t._options=n,t},t._options={},["gas","gasPrice","value","from"].forEach(function(n){t[n]=function(e){return t._options[n]=e,t}})},f=function(t,n,a){var u=r.inputParser(n),f=r.outputParser(n);o.filterFunctions(n).forEach(function(s){var c=o.extractDisplayName(s.name),l=o.extractTypeName(s.name),p=function(){var o=Array.prototype.slice.call(arguments),p=r.signatureFromAscii(s.name),m=u[c][l].apply(null,o),h=t._options||{};h.to=a,h.data=p+m;var d=t._isTransact===!0||t._isTransact!==!1&&!s.constant,g=h.collapse!==!1;if(t._options={},t._isTransact=null,d)return i({abi:n,address:a,method:s.name,params:o}),void e.eth.transact(h);var v=e.eth.call(h),y=f[c][l](v);return g&&(1===y.length?y=y[0]:0===y.length&&(y=null)),y};void 0===t[c]&&(t[c]=p),t[c][l]=p})},s=function(t,n,e){t.address=e,t._onWatchEventResult=function(t){var e=event.getMatchingEvent(o.filterEvents(n)),r=a.outputParser(e);return r(t)},Object.defineProperty(t,"topic",{get:function(){return o.filterEvents(n).map(function(t){return r.eventSignatureFromAscii(t.name)})}})},c=function(t,n,i){o.filterEvents(n).forEach(function(n){var u=function(){var t=Array.prototype.slice.call(arguments),o=r.eventSignatureFromAscii(n.name),u=a.inputParser(i,o,n),f=u.apply(null,t),s=function(t){var e=a.outputParser(n);return e(t)};return e.eth.watch(f,void 0,void 0,s)};u._isEvent=!0;var f=o.extractDisplayName(n.name),s=o.extractTypeName(n.name);void 0===t[f]&&(t[f]=u),t[f][s]=u})},l=function(t,n){n.forEach(function(t){if(-1===t.name.indexOf("(")){var n=t.name,e=t.inputs.map(function(t){return t.type}).join();t.name=n+"("+e+")"}});var e={};return u(e),f(e,n,t),s(e,n,t),c(e,n,t),e};n.exports=l},{"./abi":1,"./event":6,"./utils":15,"./web3":17}],4:[function(t,n){var e=function(){return[{name:"put",call:"db_put"},{name:"get",call:"db_get"},{name:"putString",call:"db_putString"},{name:"getString",call:"db_getString"}]};n.exports={methods:e}},{}],5:[function(t,n){var e=function(){var t=function(t){return"string"==typeof t[0]?"eth_blockByHash":"eth_blockByNumber"},n=function(t){return"string"==typeof t[0]?"eth_transactionByHash":"eth_transactionByNumber"},e=function(t){return"string"==typeof t[0]?"eth_uncleByHash":"eth_uncleByNumber"},r=function(t){return"string"==typeof t[0]?"eth_transactionCountByHash":"eth_transactionCountByNumber"},o=function(t){return"string"==typeof t[0]?"eth_uncleCountByHash":"eth_uncleCountByNumber"};return[{name:"balanceAt",call:"eth_balanceAt"},{name:"stateAt",call:"eth_stateAt"},{name:"storageAt",call:"eth_storageAt"},{name:"countAt",call:"eth_countAt"},{name:"codeAt",call:"eth_codeAt"},{name:"transact",call:"eth_transact"},{name:"call",call:"eth_call"},{name:"block",call:t},{name:"transaction",call:n},{name:"uncle",call:e},{name:"compilers",call:"eth_compilers"},{name:"flush",call:"eth_flush"},{name:"lll",call:"eth_lll"},{name:"solidity",call:"eth_solidity"},{name:"serpent",call:"eth_serpent"},{name:"logs",call:"eth_logs"},{name:"transactionCount",call:r},{name:"uncleCount",call:o}]},r=function(){return[{name:"coinbase",getter:"eth_coinbase",setter:"eth_setCoinbase"},{name:"listening",getter:"eth_listening",setter:"eth_setListening"},{name:"mining",getter:"eth_mining",setter:"eth_setMining"},{name:"gasPrice",getter:"eth_gasPrice"},{name:"accounts",getter:"eth_accounts"},{name:"peerCount",getter:"eth_peerCount"},{name:"defaultBlock",getter:"eth_defaultBlock",setter:"eth_setDefaultBlock"},{name:"number",getter:"eth_number"}]};n.exports={methods:e,properties:r}},{}],6:[function(t,n){var e=t("./abi"),r=t("./utils"),o=function(t,n){return t.filter(function(t){return t.indexed===n})},a=function(t,n){var e=r.findIndex(t,function(t){return t.name===n});return-1===e?void console.error("indexed param with name "+n+" not found"):t[e]},i=function(t,n){return Object.keys(n).map(function(r){var i=[a(o(t.inputs,!0),r)],u=n[r];return u instanceof Array?u.map(function(t){return e.formatInput(i,[t])}):e.formatInput(i,[u])})},u=function(t,n,e){return function(r,o){var a=o||{};return a.address=t,a.topic=[],a.topic.push(n),r&&(a.topic=a.topic.concat(i(e,r))),a}},f=function(t,n,e){var r=n.slice(),o=e.slice();return t.reduce(function(t,n){var e;return e=n.indexed?r.splice(0,1)[0]:o.splice(0,1)[0],t[n.name]=e,t},{})},s=function(t){return function(n){var a={event:r.extractDisplayName(t.name),number:n.number,args:{}};if(n.topics=n.topic,!n.topic)return a;var i=o(t.inputs,!0),u="0x"+n.topic.slice(1,n.topic.length).map(function(t){return t.slice(2)}).join(""),s=e.formatOutput(i,u),c=o(t.inputs,!1),l=e.formatOutput(c,n.data);return a.args=f(t.inputs,s,l),a}},c=function(t,n){for(var r=0;re;e+=2){var o=parseInt(t.substr(e,2),16);if(0===o)break;n+=String.fromCharCode(o)}return n},a=function(t){for(var n="",e=0;e3e3&&r2?t.substring(2):"0",new BigNumber(t,16).toString(10)},fromDecimal:function(t){return"0x"+new BigNumber(t).toString(16)},toEth:u.toEth,eth:{contractFromAbi:function(t){return function(n){n=n||"0xc6d9d2cd449a754c494264e1809c50e34d64562b";var e=g.eth.contract(n,t);return e.address=n,e}},watch:function(t,n,e,r){return t._isEvent?t(n,e):i(t,h,r)}},db:{},shh:{watch:function(t){return i(t,d)}},setProvider:function(t){g.manager.setProvider(t)},reset:function(){g.manager.reset()}};c(g,s()),c(g.eth,e.methods()),l(g.eth,e.properties()),c(g.db,r.methods()),c(g.shh,o.methods()),c(h,a.eth()),c(d,a.shh()),n.exports=g},{"./db":4,"./eth":5,"./filter":7,"./requestmanager":12,"./shh":13,"./utils":15,"./watches":16}],web3:[function(t,n){var e=t("./lib/web3");e.providers.HttpSyncProvider=t("./lib/httpsync"),e.providers.QtSyncProvider=t("./lib/qtsync"),e.eth.contract=t("./lib/contract"),e.abi=t("./lib/abi"),n.exports=e},{"./lib/abi":1,"./lib/contract":3,"./lib/httpsync":9,"./lib/qtsync":11,"./lib/web3":17}]},{},["web3"]); \ No newline at end of file +require=function t(n,e,r){function o(i,u){if(!e[i]){if(!n[i]){var f="function"==typeof require&&require;if(!u&&f)return f(i,!0);if(a)return a(i,!0);var s=new Error("Cannot find module '"+i+"'");throw s.code="MODULE_NOT_FOUND",s}var c=e[i]={exports:{}};n[i][0].call(c.exports,function(t){var e=n[i][1][t];return o(e?e:t)},c,c.exports,t,n,e,r)}return e[i].exports}for(var a="function"==typeof require&&require,i=0;iv;v++)g.push(h(n.slice(0,f))),n=n.slice(f);e.push(g)}else r.prefixedType("string")(t[s].type)?(c=c.slice(f),e.push(h(n.slice(0,f))),n=n.slice(f)):(e.push(h(n.slice(0,f))),n=n.slice(f))}),e},h=function(t){var n={};return t.forEach(function(t){var r=e.extractDisplayName(t.name),o=e.extractTypeName(t.name),a=function(){var n=Array.prototype.slice.call(arguments);return c(t.inputs,n)};void 0===n[r]&&(n[r]=a),n[r][o]=a}),n},d=function(t){var n={};return t.forEach(function(t){var r=e.extractDisplayName(t.name),o=e.extractTypeName(t.name),a=function(n){return m(t.outputs,n)};void 0===n[r]&&(n[r]=a),n[r][o]=a}),n};n.exports={inputParser:h,outputParser:d,formatInput:c,formatOutput:m}},{"./const":2,"./formatters":8,"./types":15,"./utils":16}],2:[function(t,n){var e=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];n.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:e,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:BigNumber.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3}},{}],3:[function(t,n){var e=t("./web3"),r=t("./abi"),o=t("./utils"),a=t("./event"),i=t("./signature"),u=function(t){e._currentContractAbi=t.abi,e._currentContractAddress=t.address,e._currentContractMethodName=t.method,e._currentContractMethodParams=t.params},f=function(t){t.call=function(n){return t._isTransact=!1,t._options=n,t},t.transact=function(n){return t._isTransact=!0,t._options=n,t},t._options={},["gas","gasPrice","value","from"].forEach(function(n){t[n]=function(e){return t._options[n]=e,t}})},s=function(t,n,a){var f=r.inputParser(n),s=r.outputParser(n);o.filterFunctions(n).forEach(function(r){var c=o.extractDisplayName(r.name),l=o.extractTypeName(r.name),p=function(){var o=Array.prototype.slice.call(arguments),p=i.functionSignatureFromAscii(r.name),m=f[c][l].apply(null,o),h=t._options||{};h.to=a,h.data=p+m;var d=t._isTransact===!0||t._isTransact!==!1&&!r.constant,g=h.collapse!==!1;if(t._options={},t._isTransact=null,d)return u({abi:n,address:a,method:r.name,params:o}),void e.eth.transact(h);var v=e.eth.call(h),y=s[c][l](v);return g&&(1===y.length?y=y[0]:0===y.length&&(y=null)),y};void 0===t[c]&&(t[c]=p),t[c][l]=p})},c=function(t,n,e){t.address=e,t._onWatchEventResult=function(t){var e=event.getMatchingEvent(o.filterEvents(n)),r=a.outputParser(e);return r(t)},Object.defineProperty(t,"topic",{get:function(){return o.filterEvents(n).map(function(t){return i.eventSignatureFromAscii(t.name)})}})},l=function(t,n,r){o.filterEvents(n).forEach(function(n){var u=function(){var t=Array.prototype.slice.call(arguments),o=i.eventSignatureFromAscii(n.name),u=a.inputParser(r,o,n),f=u.apply(null,t),s=function(t){var e=a.outputParser(n);return e(t)};return e.eth.watch(f,void 0,void 0,s)};u._isEvent=!0;var f=o.extractDisplayName(n.name),s=o.extractTypeName(n.name);void 0===t[f]&&(t[f]=u),t[f][s]=u})},p=function(t,n){n.forEach(function(t){if(-1===t.name.indexOf("(")){var n=t.name,e=t.inputs.map(function(t){return t.type}).join();t.name=n+"("+e+")"}});var e={};return f(e),s(e,n,t),c(e,n,t),l(e,n,t),e};n.exports=p},{"./abi":1,"./event":6,"./signature":14,"./utils":16,"./web3":18}],4:[function(t,n){var e=function(){return[{name:"put",call:"db_put"},{name:"get",call:"db_get"},{name:"putString",call:"db_putString"},{name:"getString",call:"db_getString"}]};n.exports={methods:e}},{}],5:[function(t,n){var e=function(){var t=function(t){return"string"==typeof t[0]?"eth_blockByHash":"eth_blockByNumber"},n=function(t){return"string"==typeof t[0]?"eth_transactionByHash":"eth_transactionByNumber"},e=function(t){return"string"==typeof t[0]?"eth_uncleByHash":"eth_uncleByNumber"},r=function(t){return"string"==typeof t[0]?"eth_transactionCountByHash":"eth_transactionCountByNumber"},o=function(t){return"string"==typeof t[0]?"eth_uncleCountByHash":"eth_uncleCountByNumber"};return[{name:"balanceAt",call:"eth_balanceAt"},{name:"stateAt",call:"eth_stateAt"},{name:"storageAt",call:"eth_storageAt"},{name:"countAt",call:"eth_countAt"},{name:"codeAt",call:"eth_codeAt"},{name:"transact",call:"eth_transact"},{name:"call",call:"eth_call"},{name:"block",call:t},{name:"transaction",call:n},{name:"uncle",call:e},{name:"compilers",call:"eth_compilers"},{name:"flush",call:"eth_flush"},{name:"lll",call:"eth_lll"},{name:"solidity",call:"eth_solidity"},{name:"serpent",call:"eth_serpent"},{name:"logs",call:"eth_logs"},{name:"transactionCount",call:r},{name:"uncleCount",call:o}]},r=function(){return[{name:"coinbase",getter:"eth_coinbase",setter:"eth_setCoinbase"},{name:"listening",getter:"eth_listening",setter:"eth_setListening"},{name:"mining",getter:"eth_mining",setter:"eth_setMining"},{name:"gasPrice",getter:"eth_gasPrice"},{name:"accounts",getter:"eth_accounts"},{name:"peerCount",getter:"eth_peerCount"},{name:"defaultBlock",getter:"eth_defaultBlock",setter:"eth_setDefaultBlock"},{name:"number",getter:"eth_number"}]};n.exports={methods:e,properties:r}},{}],6:[function(t,n){var e=t("./abi"),r=t("./utils"),o=t("./signature"),a=function(t,n){return t.filter(function(t){return t.indexed===n})},i=function(t,n){var e=r.findIndex(t,function(t){return t.name===n});return-1===e?void console.error("indexed param with name "+n+" not found"):t[e]},u=function(t,n){return Object.keys(n).map(function(r){var o=[i(a(t.inputs,!0),r)],u=n[r];return u instanceof Array?u.map(function(t){return e.formatInput(o,[t])}):e.formatInput(o,[u])})},f=function(t,n,e){return function(r,o){var a=o||{};return a.address=t,a.topic=[],a.topic.push(n),r&&(a.topic=a.topic.concat(u(e,r))),a}},s=function(t,n,e){var r=n.slice(),o=e.slice();return t.reduce(function(t,n){var e;return e=n.indexed?r.splice(0,1)[0]:o.splice(0,1)[0],t[n.name]=e,t},{})},c=function(t){return function(n){var o={event:r.extractDisplayName(t.name),number:n.number,hash:n.hash,args:{}};if(n.topics=n.topic,!n.topic)return o;var i=a(t.inputs,!0),u="0x"+n.topic.slice(1,n.topic.length).map(function(t){return t.slice(2)}).join(""),f=e.formatOutput(i,u),c=a(t.inputs,!1),l=e.formatOutput(c,n.data);return o.args=s(t.inputs,f,l),o}},l=function(t,n){for(var e=0;ee;e+=2){var o=parseInt(t.substr(e,2),16);if(0===o)break;n+=String.fromCharCode(o)}return n},a=function(t){for(var n="",e=0;e3e3&&r2?t.substring(2):"0",new BigNumber(t,16).toString(10)},fromDecimal:function(t){return"0x"+new BigNumber(t).toString(16)},toEth:u.toEth,eth:{contractFromAbi:function(t){return function(n){n=n||"0xc6d9d2cd449a754c494264e1809c50e34d64562b";var e=g.eth.contract(n,t);return e.address=n,e}},watch:function(t,n,e,r){return t._isEvent?t(n,e):i(t,h,r)}},db:{},shh:{watch:function(t){return i(t,d)}},setProvider:function(t){g.manager.setProvider(t)},reset:function(){g.manager.reset()}};c(g,s()),c(g.eth,e.methods()),l(g.eth,e.properties()),c(g.db,r.methods()),c(g.shh,o.methods()),c(h,a.eth()),c(d,a.shh()),n.exports=g},{"./db":4,"./eth":5,"./filter":7,"./requestmanager":12,"./shh":13,"./utils":16,"./watches":17}],web3:[function(t,n){var e=t("./lib/web3");e.providers.HttpSyncProvider=t("./lib/httpsync"),e.providers.QtSyncProvider=t("./lib/qtsync"),e.eth.contract=t("./lib/contract"),e.abi=t("./lib/abi"),n.exports=e},{"./lib/abi":1,"./lib/contract":3,"./lib/httpsync":9,"./lib/qtsync":11,"./lib/web3":18}]},{},["web3"]); \ No newline at end of file diff --git a/lib/abi.js b/lib/abi.js index db4e916d7..ff06e8949 100644 --- a/lib/abi.js +++ b/lib/abi.js @@ -21,7 +21,6 @@ * @date 2014 */ -var web3 = require('./web3'); var utils = require('./utils'); var types = require('./types'); var c = require('./const'); @@ -40,11 +39,11 @@ var arrayType = function (type) { var dynamicTypeBytes = function (type, value) { // TODO: decide what to do with array of strings if (arrayType(type) || type === 'string') // only string itself that is dynamic; stringX is static length. - return f.formatInputInt(value.length); + return f.formatInputInt(value.length); return ""; }; -var inputTypes = types.inputTypes(); +var inputTypes = types.inputTypes(); /// Formats input params to bytes /// @param abi contract method inputs @@ -52,13 +51,16 @@ var inputTypes = types.inputTypes(); /// @returns bytes representation of input params var formatInput = function (inputs, params) { var bytes = ""; + var toAppendConstant = ""; + var toAppendArrayContent = ""; - /// first we iterate in search for dynamic + /// first we iterate in search for dynamic inputs.forEach(function (input, index) { bytes += dynamicTypeBytes(input.type, params[index]); }); inputs.forEach(function (input, i) { + /*jshint maxcomplexity:5 */ var typeMatch = false; for (var j = 0; j < inputTypes.length && !typeMatch; j++) { typeMatch = inputTypes[j].type(inputs[i].type, params[i]); @@ -68,17 +70,19 @@ var formatInput = function (inputs, params) { } var formatter = inputTypes[j - 1].format; - var toAppend = ""; if (arrayType(inputs[i].type)) - toAppend = params[i].reduce(function (acc, curr) { + toAppendArrayContent += params[i].reduce(function (acc, curr) { return acc + formatter(curr); }, ""); + else if (inputs[i].type === 'string') + toAppendArrayContent += formatter(params[i]); else - toAppend = formatter(params[i]); - - bytes += toAppend; + toAppendConstant += formatter(params[i]); }); + + bytes += toAppendConstant + toAppendArrayContent; + return bytes; }; @@ -88,14 +92,14 @@ var dynamicBytesLength = function (type) { return 0; }; -var outputTypes = types.outputTypes(); +var outputTypes = types.outputTypes(); /// Formats output bytes back to param list /// @param contract abi method outputs -/// @param bytes representtion of output -/// @returns array of output params +/// @param bytes representtion of output +/// @returns array of output params var formatOutput = function (outs, output) { - + output = output.slice(2); var result = []; var padding = c.ETH_PADDING * 2; @@ -103,7 +107,7 @@ var formatOutput = function (outs, output) { var dynamicPartLength = outs.reduce(function (acc, curr) { return acc + dynamicBytesLength(curr.type); }, 0); - + var dynamicPart = output.slice(0, dynamicPartLength); output = output.slice(dynamicPartLength); @@ -124,13 +128,13 @@ var formatOutput = function (outs, output) { dynamicPart = dynamicPart.slice(padding); var array = []; for (var k = 0; k < size; k++) { - array.push(formatter(output.slice(0, padding))); + array.push(formatter(output.slice(0, padding))); output = output.slice(padding); } result.push(array); } else if (types.prefixedType('string')(outs[i].type)) { - dynamicPart = dynamicPart.slice(padding); + dynamicPart = dynamicPart.slice(padding); result.push(formatter(output.slice(0, padding))); output = output.slice(padding); } else { @@ -148,14 +152,14 @@ var formatOutput = function (outs, output) { var inputParser = function (json) { var parser = {}; json.forEach(function (method) { - var displayName = utils.extractDisplayName(method.name); + var displayName = utils.extractDisplayName(method.name); var typeName = utils.extractTypeName(method.name); var impl = function () { var params = Array.prototype.slice.call(arguments); return formatInput(method.inputs, params); }; - + if (parser[displayName] === undefined) { parser[displayName] = impl; } @@ -172,7 +176,7 @@ var outputParser = function (json) { var parser = {}; json.forEach(function (method) { - var displayName = utils.extractDisplayName(method.name); + var displayName = utils.extractDisplayName(method.name); var typeName = utils.extractTypeName(method.name); var impl = function (output) { @@ -189,22 +193,9 @@ var outputParser = function (json) { return parser; }; -/// @param function/event name for which we want to get signature -/// @returns signature of function/event with given name -var signatureFromAscii = function (name) { - return web3.sha3(web3.fromAscii(name)).slice(0, 2 + c.ETH_SIGNATURE_LENGTH * 2); -}; - -var eventSignatureFromAscii = function (name) { - return web3.sha3(web3.fromAscii(name)); -}; - module.exports = { inputParser: inputParser, outputParser: outputParser, formatInput: formatInput, - formatOutput: formatOutput, - signatureFromAscii: signatureFromAscii, - eventSignatureFromAscii: eventSignatureFromAscii + formatOutput: formatOutput }; - diff --git a/lib/contract.js b/lib/contract.js index 4e7304aab..87a063921 100644 --- a/lib/contract.js +++ b/lib/contract.js @@ -24,6 +24,7 @@ var web3 = require('./web3'); var abi = require('./abi'); var utils = require('./utils'); var eventImpl = require('./event'); +var signature = require('./signature'); var exportNatspecGlobals = function (vars) { // it's used byt natspec.js @@ -71,12 +72,12 @@ var addFunctionsToContract = function (contract, desc, address) { var impl = function () { /*jshint maxcomplexity:7 */ var params = Array.prototype.slice.call(arguments); - var signature = abi.signatureFromAscii(method.name); + var sign = signature.functionSignatureFromAscii(method.name); var parsed = inputParser[displayName][typeName].apply(null, params); var options = contract._options || {}; options.to = address; - options.data = signature + parsed; + options.data = sign + parsed; var isTransact = contract._isTransact === true || (contract._isTransact !== false && !method.constant); var collapse = options.collapse !== false; @@ -130,7 +131,7 @@ var addEventRelatedPropertiesToContract = function (contract, desc, address) { Object.defineProperty(contract, 'topic', { get: function() { return utils.filterEvents(desc).map(function (e) { - return abi.eventSignatureFromAscii(e.name); + return signature.eventSignatureFromAscii(e.name); }); } }); @@ -143,8 +144,8 @@ var addEventsToContract = function (contract, desc, address) { var impl = function () { var params = Array.prototype.slice.call(arguments); - var signature = abi.eventSignatureFromAscii(e.name); - var event = eventImpl.inputParser(address, signature, e); + var sign = signature.eventSignatureFromAscii(e.name); + var event = eventImpl.inputParser(address, sign, e); var o = event.apply(null, params); var outputFormatter = function (data) { var parser = eventImpl.outputParser(e); diff --git a/lib/event.js b/lib/event.js index d462491f0..81344c24b 100644 --- a/lib/event.js +++ b/lib/event.js @@ -22,6 +22,7 @@ var abi = require('./abi'); var utils = require('./utils'); +var signature = require('./signature'); /// filter inputs array && returns only indexed (or not) inputs /// @param inputs array @@ -60,14 +61,14 @@ var indexedParamsToTopics = function (event, indexed) { }); }; -var inputParser = function (address, signature, event) { +var inputParser = function (address, sign, event) { // valid options are 'earliest', 'latest', 'offset' and 'max', as defined for 'eth.watch' return function (indexed, options) { var o = options || {}; o.address = address; o.topic = []; - o.topic.push(signature); + o.topic.push(sign); if (indexed) { o.topic = o.topic.concat(indexedParamsToTopics(event, indexed)); } @@ -96,6 +97,7 @@ var outputParser = function (event) { var result = { event: utils.extractDisplayName(event.name), number: output.number, + hash: output.hash, args: {} }; @@ -119,8 +121,8 @@ var outputParser = function (event) { var getMatchingEvent = function (events, payload) { for (var i = 0; i < events.length; i++) { - var signature = abi.eventSignatureFromAscii(events[i].name); - if (signature === payload.topic[0]) { + var sign = signature.eventSignatureFromAscii(events[i].name); + if (sign === payload.topic[0]) { return events[i]; } } diff --git a/lib/httpsync.js b/lib/httpsync.js index 90f3ee454..b90fa746e 100644 --- a/lib/httpsync.js +++ b/lib/httpsync.js @@ -27,7 +27,7 @@ if (process.env.NODE_ENV !== 'build') { var HttpSyncProvider = function (host) { this.handlers = []; - this.host = host || 'http://localhost:8080'; + this.host = host || 'http://127.0.0.1:8080'; }; HttpSyncProvider.prototype.send = function (payload) { diff --git a/lib/signature.js b/lib/signature.js new file mode 100644 index 000000000..511762166 --- /dev/null +++ b/lib/signature.js @@ -0,0 +1,42 @@ +/* + 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 signature.js + * @authors: + * Marek Kotewicz + * @date 2015 + */ + +var web3 = require('./web3'); +var c = require('./const'); + +/// @param function name for which we want to get signature +/// @returns signature of function with given name +var functionSignatureFromAscii = function (name) { + return web3.sha3(web3.fromAscii(name)).slice(0, 2 + c.ETH_SIGNATURE_LENGTH * 2); +}; + +/// @param event name for which we want to get signature +/// @returns signature of event with given name +var eventSignatureFromAscii = function (name) { + return web3.sha3(web3.fromAscii(name)); +}; + +module.exports = { + functionSignatureFromAscii: functionSignatureFromAscii, + eventSignatureFromAscii: eventSignatureFromAscii +}; + diff --git a/package.json b/package.json index b711512a7..340200d0d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ethereum.js", "namespace": "ethereum", - "version": "0.0.15", + "version": "0.0.16", "description": "Ethereum Compatible JavaScript API", "main": "./index.js", "directories": { diff --git a/test/abi.inputParser.js b/test/abi.inputParser.js index 12b735153..edfc2b58f 100644 --- a/test/abi.inputParser.js +++ b/test/abi.inputParser.js @@ -29,7 +29,7 @@ describe('abi', function() { d[0].inputs = [ { type: "uint" } ]; - + // when var parser = abi.inputParser(d); @@ -37,7 +37,7 @@ describe('abi', function() { assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); assert.equal( - parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); assert.equal( @@ -67,7 +67,7 @@ describe('abi', function() { assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); assert.equal( - parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); assert.equal( @@ -80,7 +80,7 @@ describe('abi', function() { assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); }); - + it('should parse input uint256', function() { // given @@ -97,7 +97,7 @@ describe('abi', function() { assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); assert.equal(parser.test(10), "000000000000000000000000000000000000000000000000000000000000000a"); assert.equal( - parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); assert.equal( @@ -108,7 +108,7 @@ describe('abi', function() { assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); - + }); it('should parse input int', function() { @@ -119,7 +119,7 @@ describe('abi', function() { d[0].inputs = [ { type: "int" } ]; - + // when var parser = abi.inputParser(d); @@ -130,7 +130,7 @@ describe('abi', function() { assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); assert.equal( - parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); assert.equal( @@ -162,7 +162,7 @@ describe('abi', function() { assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); assert.equal( - parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); assert.equal( @@ -177,7 +177,7 @@ describe('abi', function() { }); it('should parse input int256', function() { - + // given var d = clone(description); @@ -195,7 +195,7 @@ describe('abi', function() { assert.equal(parser.test(-2), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); assert.equal(parser.test(-16), "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0"); assert.equal( - parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + parser.test("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ); assert.equal( @@ -206,11 +206,11 @@ describe('abi', function() { assert.equal(parser.test(3.9), "0000000000000000000000000000000000000000000000000000000000000003"); assert.equal(parser.test('0.1'), "0000000000000000000000000000000000000000000000000000000000000000"); assert.equal(parser.test('3.9'), "0000000000000000000000000000000000000000000000000000000000000003"); - + }); it('should parse input bool', function() { - + // given var d = clone(description); @@ -235,14 +235,14 @@ describe('abi', function() { d[0].inputs = [ { type: "hash" } ]; - + // when var parser = abi.inputParser(d); // then assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); - }); + }); it('should parse input hash256', function() { @@ -272,7 +272,7 @@ describe('abi', function() { // when var parser = abi.inputParser(d); - + // then assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); }); @@ -285,17 +285,17 @@ describe('abi', function() { d[0].inputs = [ { type: "address" } ]; - + // when var parser = abi.inputParser(d) - + // then assert.equal(parser.test("0x407d73d8a49eeb85d32cf465507dd71d507100c1"), "000000000000000000000000407d73d8a49eeb85d32cf465507dd71d507100c1"); }); it('should parse input string', function () { - + // given var d = clone(description); @@ -308,8 +308,9 @@ describe('abi', function() { // then assert.equal( - parser.test('hello'), - "000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000" + parser.test('hello'), + "0000000000000000000000000000000000000000000000000000000000000005" + + "68656c6c6f000000000000000000000000000000000000000000000000000000" ); assert.equal( parser.test('world'), @@ -317,8 +318,52 @@ describe('abi', function() { ); }); + it('should parse input int followed by a string', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "int" }, + { type: "string" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal( + parser.test(9, 'hello'), + "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000009" + + "68656c6c6f000000000000000000000000000000000000000000000000000000" + ); + }); + + it('should parse input string followed by an int', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "string" }, + { type: "int" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal( + parser.test('hello', 9), + "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000009" + + "68656c6c6f000000000000000000000000000000000000000000000000000000" + ); + }); + it('should use proper method name', function () { - + // given var d = clone(description); d[0].name = 'helloworld(int)'; @@ -334,9 +379,9 @@ describe('abi', function() { assert.equal(parser.helloworld['int'](1), "0000000000000000000000000000000000000000000000000000000000000001"); }); - + it('should parse multiple methods', function () { - + // given var d = [{ name: "test", @@ -356,14 +401,14 @@ describe('abi', function() { //then assert.equal(parser.test(1), "0000000000000000000000000000000000000000000000000000000000000001"); assert.equal( - parser.test2('hello'), + parser.test2('hello'), "000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000" ); }); it('should parse input array of ints', function () { - + // given var d = clone(description); @@ -377,14 +422,91 @@ describe('abi', function() { // then assert.equal( parser.test([5, 6]), - "0000000000000000000000000000000000000000000000000000000000000002" + - "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000006" + ); + }); + + it('should parse an array followed by an int', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "int[]" }, + { type: "int" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal( + parser.test([5, 6], 3), + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000003" + + "0000000000000000000000000000000000000000000000000000000000000005" + "0000000000000000000000000000000000000000000000000000000000000006" ); }); + it('should parse an int followed by an array', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "int" }, + { type: "int[]" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal( + parser.test(3, [5, 6]), + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000003" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000006" + ); + }); + + it('should parse mixture of arrays and ints', function () { + + // given + var d = clone(description); + + d[0].inputs = [ + { type: "int" }, + { type: "int[]" }, + { type: "int" }, + { type: "int[]" } + ]; + + // when + var parser = abi.inputParser(d); + + // then + assert.equal( + parser.test(3, [5, 6, 1, 2], 7, [8, 9]), + "0000000000000000000000000000000000000000000000000000000000000004" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000003" + + "0000000000000000000000000000000000000000000000000000000000000007" + + "0000000000000000000000000000000000000000000000000000000000000005" + + "0000000000000000000000000000000000000000000000000000000000000006" + + "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000002" + + "0000000000000000000000000000000000000000000000000000000000000008" + + "0000000000000000000000000000000000000000000000000000000000000009" + ); + }); + it('should parse input real', function () { - + // given var d = clone(description); @@ -396,15 +518,15 @@ describe('abi', function() { var parser = abi.inputParser(d); // then - assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000"); - assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000"); - assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000"); - assert.equal(parser.test([-1]), "ffffffffffffffffffffffffffffffff00000000000000000000000000000000"); - + assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000"); + assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000"); + assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000"); + assert.equal(parser.test([-1]), "ffffffffffffffffffffffffffffffff00000000000000000000000000000000"); + }); - + it('should parse input ureal', function () { - + // given var d = clone(description); @@ -416,12 +538,11 @@ describe('abi', function() { var parser = abi.inputParser(d); // then - assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000"); - assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000"); - assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000"); - + assert.equal(parser.test([1]), "0000000000000000000000000000000100000000000000000000000000000000"); + assert.equal(parser.test([2.125]), "0000000000000000000000000000000220000000000000000000000000000000"); + assert.equal(parser.test([8.5]), "0000000000000000000000000000000880000000000000000000000000000000"); + }); }); }); - From 9543f81e5f1a11770856777a1cccfb2f7464251a Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 4 Mar 2015 11:12:22 +0100 Subject: [PATCH 39/54] - Close project properly --- mix/qml/TransactionLog.qml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mix/qml/TransactionLog.qml b/mix/qml/TransactionLog.qml index 2821e235c..8e25b0812 100644 --- a/mix/qml/TransactionLog.qml +++ b/mix/qml/TransactionLog.qml @@ -38,6 +38,12 @@ Item { if (codeModel.hasContract && !clientModel.running) projectModel.stateListModel.debugDefaultState(); } + onProjectClosed: + { + fullModel.clear(); + transactionModel.clear(); + callModel.clear(); + } } ComboBox { From 3874c78d068acf1328394883abcf56fec7f36ed7 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 4 Mar 2015 11:53:11 +0100 Subject: [PATCH 40/54] More style fixes --- libdevcore/StructuredLogger.cpp | 12 ++++++++---- libethereum/BlockChain.cpp | 3 ++- libp2p/Host.cpp | 3 ++- libp2p/Host.h | 3 ++- libwebthree/WebThree.h | 2 +- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/libdevcore/StructuredLogger.cpp b/libdevcore/StructuredLogger.cpp index cb6acd501..d93a9496e 100644 --- a/libdevcore/StructuredLogger.cpp +++ b/libdevcore/StructuredLogger.cpp @@ -80,7 +80,8 @@ void StructuredLogger::stopping(string const& _clientImpl, const char* _ethVersi } } -void StructuredLogger::p2pConnected(string const& _id, +void StructuredLogger::p2pConnected( + string const& _id, bi::tcp::endpoint const& _addr, chrono::system_clock::time_point const& _ts, string const& _remoteVersion, @@ -117,7 +118,8 @@ void StructuredLogger::p2pDisconnected(string const& _id, bi::tcp::endpoint cons } } -void StructuredLogger::minedNewBlock(string const& _hash, +void StructuredLogger::minedNewBlock( + string const& _hash, string const& _blockNumber, string const& _chainHeadHash, string const& _prevHash) @@ -135,7 +137,8 @@ void StructuredLogger::minedNewBlock(string const& _hash, } } -void StructuredLogger::chainReceivedNewBlock(string const& _hash, +void StructuredLogger::chainReceivedNewBlock( + string const& _hash, string const& _blockNumber, string const& _chainHeadHash, string const& _remoteID, @@ -155,7 +158,8 @@ void StructuredLogger::chainReceivedNewBlock(string const& _hash, } } -void StructuredLogger::chainNewHead(string const& _hash, +void StructuredLogger::chainNewHead( + string const& _hash, string const& _blockNumber, string const& _chainHeadHash, string const& _prevHash) diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 784621a69..aabce4d4b 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -323,7 +323,8 @@ h256s BlockChain::import(bytes const& _block, OverlayDB const& _db) 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."; h256s ret; diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index bb97f06e4..a4f7bcd92 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -164,7 +164,8 @@ void Host::registerPeer(std::shared_ptr _s, CapDescs const& _caps) _s->m_peer->peerEndpoint(), _s->m_peer->m_lastConnected, _s->m_info.clientVersion, - peerCount()); + peerCount() + ); RecursiveGuard l(x_sessions); // TODO: temporary loose-coupling; if m_peers already has peer, // it is same as _s->m_peer. (fixing next PR) diff --git a/libp2p/Host.h b/libp2p/Host.h index 0eefa6f90..48e678030 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -85,7 +85,8 @@ class Host: public Worker public: /// Start server, listening for connections on the given port. - Host(std::string const& _clientVersion, + Host( + std::string const& _clientVersion, NetworkPreferences const& _n = NetworkPreferences(), bytesConstRef _restoreNetwork = bytesConstRef() ); diff --git a/libwebthree/WebThree.h b/libwebthree/WebThree.h index 66cd4c556..4a3bee59b 100644 --- a/libwebthree/WebThree.h +++ b/libwebthree/WebThree.h @@ -105,7 +105,7 @@ public: /// ethereum() may be safely static_cast()ed to a eth::Client*. WebThreeDirect( std::string const& _clientVersion, - std::string const& _dbPath, + std::string const& _dbPath, bool _forceClean = false, std::set const& _interfaces = {"eth", "shh"}, p2p::NetworkPreferences const& _n = p2p::NetworkPreferences(), From 4f109d29a64257181b46f4d1ecc05c4341548a24 Mon Sep 17 00:00:00 2001 From: jhuntley Date: Fri, 16 Jan 2015 16:37:20 -0500 Subject: [PATCH 41/54] Mingw cmake updates. Make sure Boost_INCLUDE_DIRS is included for each library using boost. When installing libraries, don't forget to copy DLLs, add target 'RUNTIME DESTINATION bin'. --- alethzero/CMakeLists.txt | 1 + libdevcrypto/CMakeLists.txt | 2 +- libethcore/CMakeLists.txt | 2 +- libethereum/CMakeLists.txt | 7 ++++++- libethereumx/CMakeLists.txt | 2 +- libevm/CMakeLists.txt | 2 +- libevmcore/CMakeLists.txt | 2 +- libjsqrc/CMakeLists.txt | 2 +- liblll/CMakeLists.txt | 2 +- libp2p/CMakeLists.txt | 7 ++++++- libserpent/CMakeLists.txt | 2 +- libsolidity/CMakeLists.txt | 2 +- libweb3jsonrpc/CMakeLists.txt | 3 ++- libwebthree/CMakeLists.txt | 3 ++- libwhisper/CMakeLists.txt | 3 ++- mix/CMakeLists.txt | 1 + neth/CMakeLists.txt | 1 + secp256k1/CMakeLists.txt | 14 +++++++++++++- third/CMakeLists.txt | 1 + 19 files changed, 44 insertions(+), 15 deletions(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 9cb1a0ff7..4af907c5d 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -13,6 +13,7 @@ aux_source_directory(. SRC_LIST) include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) include_directories(BEFORE ..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) +include_directories(${Boost_INCLUDE_DIRS}) qt5_wrap_ui(ui_Main.h Main.ui) qt5_wrap_ui(ui_Debugger.h Debugger.ui) diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index e3c3a1677..aab20c0b8 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -28,6 +28,6 @@ target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} devcore) -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt index 920f9f652..1d17525a0 100644 --- a/libethcore/CMakeLists.txt +++ b/libethcore/CMakeLists.txt @@ -25,6 +25,6 @@ endif() target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcore) -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index 86157fdc2..94a4e4497 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -13,6 +13,7 @@ aux_source_directory(. SRC_LIST) include_directories(BEFORE ..) include_directories(${LEVELDB_INCLUDE_DIRS}) +include_directories(${Boost_INCLUDE_DIRS}) set(EXECUTABLE ethereum) @@ -35,6 +36,10 @@ target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} secp256k1) -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +if (CMAKE_COMPILER_IS_MINGW) + target_link_libraries(${EXECUTABLE} ssp shlwapi) +endif() + +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libethereumx/CMakeLists.txt b/libethereumx/CMakeLists.txt index 373ff8d71..d8d3021f0 100644 --- a/libethereumx/CMakeLists.txt +++ b/libethereumx/CMakeLists.txt @@ -30,6 +30,6 @@ target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} secp256k1) -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index b04df70ea..b747acf6f 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -34,6 +34,6 @@ if (EVMJIT) target_link_libraries(${EXECUTABLE} evmjit-cpp) endif() -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libevmcore/CMakeLists.txt b/libevmcore/CMakeLists.txt index 0f8494804..b57d52fa3 100644 --- a/libevmcore/CMakeLists.txt +++ b/libevmcore/CMakeLists.txt @@ -26,6 +26,6 @@ endif() target_link_libraries(${EXECUTABLE} devcore) -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libjsqrc/CMakeLists.txt b/libjsqrc/CMakeLists.txt index 2635bc558..68500ada6 100644 --- a/libjsqrc/CMakeLists.txt +++ b/libjsqrc/CMakeLists.txt @@ -22,4 +22,4 @@ if (ETH_NODE AND ETH_NPM) add_dependencies(jsqrc ethereumjs) endif() -install( TARGETS jsqrc ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( TARGETS jsqrc RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) diff --git a/liblll/CMakeLists.txt b/liblll/CMakeLists.txt index 3b9dc6030..e60522a7c 100644 --- a/liblll/CMakeLists.txt +++ b/liblll/CMakeLists.txt @@ -27,6 +27,6 @@ endif() target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcore) -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libp2p/CMakeLists.txt b/libp2p/CMakeLists.txt index 83309be78..eb19d25fe 100644 --- a/libp2p/CMakeLists.txt +++ b/libp2p/CMakeLists.txt @@ -15,6 +15,7 @@ include_directories(BEFORE ..) # we may not use it in libp2p, but one of our dependecies is including leveldb in header file # and windows is failing to build without that include_directories(${LEVELDB_INCLUDE_DIRS}) +include_directories(${Boost_INCLUDE_DIRS}) if (MINIUPNPC_FOUND) include_directories(${MINIUPNPC_INCLUDE_DIRS}) @@ -37,6 +38,10 @@ endif() target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcore) -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +if (CMAKE_COMPILER_IS_MINGW) + target_link_libraries(${EXECUTABLE} ws2_32 mswsock) +endif() + +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libserpent/CMakeLists.txt b/libserpent/CMakeLists.txt index 45dfa339d..71385b223 100644 --- a/libserpent/CMakeLists.txt +++ b/libserpent/CMakeLists.txt @@ -27,6 +27,6 @@ target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcore) -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 2b1059c69..b42b6e5c0 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -30,6 +30,6 @@ target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcrypto) -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 867dd7e7e..b445f77ff 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -14,6 +14,7 @@ include_directories(BEFORE ..) include_directories(${MHD_INCLUDE_DIRS}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIRS}) +include_directories(${Boost_INCLUDE_DIRS}) set(EXECUTABLE web3jsonrpc) @@ -52,7 +53,7 @@ if (ETH_JSON_RPC_STUB) add_dependencies(${EXECUTABLE} jsonrpcstub) endif() -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libwebthree/CMakeLists.txt b/libwebthree/CMakeLists.txt index f22d4f94f..ac97a9e2b 100644 --- a/libwebthree/CMakeLists.txt +++ b/libwebthree/CMakeLists.txt @@ -13,6 +13,7 @@ aux_source_directory(. SRC_LIST) include_directories(BEFORE ..) include_directories(${LEVELDB_INCLUDE_DIRS}) +include_directories(${Boost_INCLUDE_DIRS}) set(EXECUTABLE webthree) @@ -35,6 +36,6 @@ target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} secp256k1) -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/libwhisper/CMakeLists.txt b/libwhisper/CMakeLists.txt index 160347484..40e764863 100644 --- a/libwhisper/CMakeLists.txt +++ b/libwhisper/CMakeLists.txt @@ -13,6 +13,7 @@ aux_source_directory(. SRC_LIST) include_directories(BEFORE ..) include_directories(${LEVELDB_INCLUDE_DIRS}) +include_directories(${Boost_INCLUDE_DIRS}) set(EXECUTABLE whisper) @@ -32,5 +33,5 @@ target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} p2p) target_link_libraries(${EXECUTABLE} secp256k1) -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/mix/CMakeLists.txt b/mix/CMakeLists.txt index 5f6dae919..0ef9c6274 100644 --- a/mix/CMakeLists.txt +++ b/mix/CMakeLists.txt @@ -12,6 +12,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) +include_directories(${Boost_INCLUDE_DIRS}) include_directories(BEFORE ..) find_package (Qt5WebEngine QUIET) diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index caf7d2f97..c500b83df 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -5,6 +5,7 @@ aux_source_directory(. SRC_LIST) include_directories(BEFORE ..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIRS}) +include_directories(${Boost_INCLUDE_DIRS}) set(EXECUTABLE neth) diff --git a/secp256k1/CMakeLists.txt b/secp256k1/CMakeLists.txt index deafa245a..ab67b86a0 100644 --- a/secp256k1/CMakeLists.txt +++ b/secp256k1/CMakeLists.txt @@ -21,6 +21,18 @@ if (APPLE OR UNIX) endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM") target_link_libraries(${EXECUTABLE} ${GMP_LIBRARIES}) +elseif (CMAKE_COMPILER_IS_MINGW) + + include_directories(${Boost_INCLUDE_DIRS}) + + if (ETH_STATIC) + add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c field_5x52_asm.asm) + else() + add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c field_5x52_asm.asm) + endif() + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -W -Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wno-unused-function -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM") + target_link_libraries(${EXECUTABLE} ${GMP_LIBRARIES}) else() include_directories(${Boost_INCLUDE_DIRS}) @@ -36,5 +48,5 @@ else() endif() -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) diff --git a/third/CMakeLists.txt b/third/CMakeLists.txt index 989677626..397f2b7a6 100644 --- a/third/CMakeLists.txt +++ b/third/CMakeLists.txt @@ -12,6 +12,7 @@ aux_source_directory(. SRC_LIST) include_directories(BEFORE ..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) +include_directories(${Boost_INCLUDE_DIRS}) qt5_wrap_ui(ui_Main.h Main.ui) From e1e7b227dfaeee8f99657f4ae2ea749f150d252e Mon Sep 17 00:00:00 2001 From: jhuntley Date: Fri, 16 Jan 2015 16:55:46 -0500 Subject: [PATCH 42/54] Avoid boost include order issue on windows: http://stackoverflow.com/questions/9750344/boostasio-winsock-and-winsock-2-compatibility-issue http://stackoverflow.com/questions/9750344/boostasio-winsock-and-winsock-2-compatibility-issue/16288859#16288859 Make sure boost/asio.hpp is included before windows.h. --- alethzero/MainWin.cpp | 1 + alethzero/MainWin.h | 1 + eth/main.cpp | 1 + libethereum/All.h | 1 + libethereum/Client.h | 1 + libethereum/EthereumHost.h | 1 + libp2p/Host.cpp | 1 + libp2p/Host.h | 1 + libp2p/Network.cpp | 1 + libp2p/Session.h | 1 + libwebthree/WebThree.cpp | 1 + libwebthree/WebThree.h | 1 + libwhisper/Common.h | 1 + libwhisper/Interface.h | 1 + libwhisper/Message.h | 1 + libwhisper/WhisperHost.h | 1 + libwhisper/WhisperPeer.h | 1 + mix/AppContext.cpp | 1 + mix/AppContext.h | 1 + mix/CodeEditorExtensionManager.cpp | 1 + mix/Extension.cpp | 3 ++- mix/Extension.h | 1 + mix/QContractDefinition.cpp | 1 + neth/main.cpp | 1 + test/TestHelper.cpp | 1 + test/fork.cpp | 2 +- test/txTest.cpp | 2 +- test/whisperTopic.cpp | 1 + third/MainWin.cpp | 18 +++++++++++------- 29 files changed, 40 insertions(+), 10 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index a4c8a7b60..966d23128 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -20,6 +20,7 @@ */ #include +#include #include #include #include diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 638469fbe..cd0c309b3 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -26,6 +26,7 @@ #endif #include +#include #include #include #include diff --git a/eth/main.cpp b/eth/main.cpp index 8014cc0fa..fa164cfda 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/libethereum/All.h b/libethereum/All.h index 24109cb87..adae84843 100644 --- a/libethereum/All.h +++ b/libethereum/All.h @@ -1,5 +1,6 @@ #pragma once +#include #include "Account.h" #include "CanonBlockChain.h" #include "Client.h" diff --git a/libethereum/Client.h b/libethereum/Client.h index 187152672..fbbe9e22c 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index dfa928675..9e2ddf6de 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index a4f7bcd92..adc408324 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/libp2p/Host.h b/libp2p/Host.h index 48e678030..ec59d105f 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff --git a/libp2p/Network.cpp b/libp2p/Network.cpp index d0276d67e..b54395aec 100644 --- a/libp2p/Network.cpp +++ b/libp2p/Network.cpp @@ -26,6 +26,7 @@ #include #endif +#include #include #include #include diff --git a/libp2p/Session.h b/libp2p/Session.h index 4d55e7d9d..2d5b937bf 100644 --- a/libp2p/Session.h +++ b/libp2p/Session.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include diff --git a/libwebthree/WebThree.cpp b/libwebthree/WebThree.cpp index 1cf478746..23dbfe0c4 100644 --- a/libwebthree/WebThree.cpp +++ b/libwebthree/WebThree.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include diff --git a/libwebthree/WebThree.h b/libwebthree/WebThree.h index 4a3bee59b..bcccc150c 100644 --- a/libwebthree/WebThree.h +++ b/libwebthree/WebThree.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/libwhisper/Common.h b/libwhisper/Common.h index 8180b0ec4..61c92f6eb 100644 --- a/libwhisper/Common.h +++ b/libwhisper/Common.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include diff --git a/libwhisper/Interface.h b/libwhisper/Interface.h index 37651a826..189c3806c 100644 --- a/libwhisper/Interface.h +++ b/libwhisper/Interface.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/libwhisper/Message.h b/libwhisper/Message.h index 7e5df5a95..4b457f251 100644 --- a/libwhisper/Message.h +++ b/libwhisper/Message.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/libwhisper/WhisperHost.h b/libwhisper/WhisperHost.h index b6e683778..701f2ef54 100644 --- a/libwhisper/WhisperHost.h +++ b/libwhisper/WhisperHost.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/libwhisper/WhisperPeer.h b/libwhisper/WhisperPeer.h index 5dd265e5a..0a30accc9 100644 --- a/libwhisper/WhisperPeer.h +++ b/libwhisper/WhisperPeer.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/mix/AppContext.cpp b/mix/AppContext.cpp index 29124a39a..513fd3103 100644 --- a/mix/AppContext.cpp +++ b/mix/AppContext.cpp @@ -22,6 +22,7 @@ * - KeyEventManager */ +#include #include #include #include diff --git a/mix/AppContext.h b/mix/AppContext.h index 268771207..f7f17ff63 100644 --- a/mix/AppContext.h +++ b/mix/AppContext.h @@ -27,6 +27,7 @@ #pragma once +#include #include #include #include diff --git a/mix/CodeEditorExtensionManager.cpp b/mix/CodeEditorExtensionManager.cpp index 97b808eb2..f81f6648e 100644 --- a/mix/CodeEditorExtensionManager.cpp +++ b/mix/CodeEditorExtensionManager.cpp @@ -20,6 +20,7 @@ * Ethereum IDE client. */ +#include #include #include #include diff --git a/mix/Extension.cpp b/mix/Extension.cpp index 8a36751a0..d4a279afa 100644 --- a/mix/Extension.cpp +++ b/mix/Extension.cpp @@ -17,13 +17,14 @@ * Ethereum IDE client. */ +#include "AppContext.h" #include #include #include #include #include #include "Extension.h" -#include "AppContext.h" + using namespace dev; using namespace dev::mix; diff --git a/mix/Extension.h b/mix/Extension.h index 98daf2918..b42fd99a2 100644 --- a/mix/Extension.h +++ b/mix/Extension.h @@ -19,6 +19,7 @@ #pragma once +#include #include #include diff --git a/mix/QContractDefinition.cpp b/mix/QContractDefinition.cpp index eacaee2f9..ca617955c 100644 --- a/mix/QContractDefinition.cpp +++ b/mix/QContractDefinition.cpp @@ -20,6 +20,7 @@ */ #include +#include #include #include #include diff --git a/neth/main.cpp b/neth/main.cpp index ca25b8d11..b6ab5a209 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index f82b72b88..4ee53f88e 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include diff --git a/test/fork.cpp b/test/fork.cpp index bc6ed87bc..934583164 100644 --- a/test/fork.cpp +++ b/test/fork.cpp @@ -19,7 +19,7 @@ * @date 2014 * Tests for different forking behavior */ - +#include #include #include #include diff --git a/test/txTest.cpp b/test/txTest.cpp index 8d067f9bb..dcb2515af 100644 --- a/test/txTest.cpp +++ b/test/txTest.cpp @@ -19,7 +19,7 @@ * @date 2014 * Simple peer transaction send test. */ - +#include #include #include #include diff --git a/test/whisperTopic.cpp b/test/whisperTopic.cpp index 4609c957d..2f90b4fb9 100644 --- a/test/whisperTopic.cpp +++ b/test/whisperTopic.cpp @@ -19,6 +19,7 @@ * @date 2014 */ #include +#include #include #include #include diff --git a/third/MainWin.cpp b/third/MainWin.cpp index 5fb5074bc..c91c416d8 100644 --- a/third/MainWin.cpp +++ b/third/MainWin.cpp @@ -20,6 +20,11 @@ */ #include + +// Make sure boost/asio.hpp is included before windows.h. +#include +#include + #include #include #include @@ -27,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -112,7 +116,7 @@ Main::Main(QWidget *parent) : statusBar()->addPermanentWidget(ui->peerCount); statusBar()->addPermanentWidget(ui->mineStatus); statusBar()->addPermanentWidget(ui->blockCount); - + connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved())); bytesConstRef networkConfig((byte*)m_networkConfig.data(), m_networkConfig.size()); @@ -124,7 +128,7 @@ Main::Main(QWidget *parent) : // m_server = unique_ptr(new WebThreeStubServer(m_httpConnector, *web3(), keysAsVector(m_myKeys))); m_server->setIdentities(keysAsVector(owned())); m_server->StartListening(); - + connect(ui->webView, &QWebView::loadStarted, [this]() { QWebFrame* f = ui->webView->page()->mainFrame(); @@ -138,16 +142,16 @@ Main::Main(QWidget *parent) : f->evaluateJavaScript(contentsOfQResource(":/js/setup.js")); }); }); - + connect(ui->webView, &QWebView::loadFinished, [=]() { }); - + connect(ui->webView, &QWebView::titleChanged, [=]() { ui->tabWidget->setTabText(0, ui->webView->title()); }); - + readSettings(); installWatches(); @@ -521,7 +525,7 @@ void Main::timerEvent(QTimerEvent*) // 7/18, Alex: aggregating timers, prelude to better threading? // Runs much faster on slower dual-core processors static int interval = 100; - + // refresh mining every 200ms if (interval / 100 % 2 == 0) refreshMining(); From 5cec8a5c6f975f923a79575203bf43756be3bc34 Mon Sep 17 00:00:00 2001 From: jhuntley Date: Fri, 16 Jan 2015 16:56:13 -0500 Subject: [PATCH 43/54] Updates for mingw support. #undef conflicting defines on windows. --- libsolidity/Token.h | 6 ++++++ libsolidity/Types.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/libsolidity/Token.h b/libsolidity/Token.h index 5e4a6317f..2c24f7aff 100644 --- a/libsolidity/Token.h +++ b/libsolidity/Token.h @@ -65,6 +65,12 @@ namespace solidity // an argument (at any position) for a TOKEN_LIST call. It does // nothing with tokens belonging to the respective category. +#if defined(__MINGW32__) +#undef IN +#undef DELETE +#undef CONST +#endif + #define IGNORE_TOKEN(name, string, precedence) #define TOKEN_LIST(T, K) \ diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 8474c6c03..99c083c00 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -67,6 +67,9 @@ private: MemberMap m_memberTypes; }; +#if defined(__MINGW32__) +#undef VOID +#endif /** * Abstract base class that forms the root of the type hierarchy. From 094bdc0af31ac1973cb3ac5be9ed8d107ea27273 Mon Sep 17 00:00:00 2001 From: jhuntley Date: Fri, 16 Jan 2015 16:56:36 -0500 Subject: [PATCH 44/54] Updates for mingw support. Make sure CXXFLAGS are checked if exported to environment before build. --- cmake/EthCompilerSettings.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 35a855a45..7cb42e0e4 100755 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -3,7 +3,7 @@ # C++11 check and activation if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") - set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -Werror -DSHAREDLIB -fPIC") + set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-unknown-pragmas -Wextra -Werror -DSHAREDLIB -fPIC ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE") From cc67b7f908bfcb20c7da31198961f1b083992bdc Mon Sep 17 00:00:00 2001 From: jhuntley Date: Fri, 16 Jan 2015 16:56:59 -0500 Subject: [PATCH 45/54] Update for mingw support, jsonrpc is also a standard path used if building and installing jsonrpccpp from source. --- cmake/FindJsonRpcCpp.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindJsonRpcCpp.cmake b/cmake/FindJsonRpcCpp.cmake index 2ca176f68..39fd3b39c 100644 --- a/cmake/FindJsonRpcCpp.cmake +++ b/cmake/FindJsonRpcCpp.cmake @@ -14,7 +14,7 @@ # only look in default directories find_path( JSON_RPC_CPP_INCLUDE_DIR - NAMES jsonrpccpp/server.h + NAMES jsonrpccpp/server.h jsonrpc/server.h PATH_SUFFIXES jsonrpc DOC "json-rpc-cpp include dir" ) From f7508dfc8a46daab6a32768fde9305bf47884e3c Mon Sep 17 00:00:00 2001 From: jhuntley Date: Wed, 21 Jan 2015 10:59:34 -0500 Subject: [PATCH 46/54] Avoid boost include order issue on windows: http://stackoverflow.com/questions/9750344/boostasio-winsock-and-winsock-2-compatibility-issue http://stackoverflow.com/questions/9750344/boostasio-winsock-and-winsock-2-compatibility-issue/16288859#16288859 Make sure boost/asio.hpp is included before windows.h. --- alethzero/OurWebThreeStubServer.h | 1 + libethereum/EthereumPeer.h | 1 + libp2p/NodeTable.h | 1 + libp2p/UDP.h | 1 + libweb3jsonrpc/WebThreeStubServer.cpp | 1 + libweb3jsonrpc/WebThreeStubServerBase.cpp | 1 + mix/ClientModel.cpp | 1 + mix/Extension.cpp | 4 +++- test/TestHelper.h | 1 + test/checkRandomTest.cpp | 1 + test/createRandomTest.cpp | 1 + test/genesis.cpp | 6 +++++- test/hexPrefix.cpp | 3 ++- test/net.cpp | 1 + test/rlp.cpp | 3 ++- test/state.cpp | 1 + test/trie.cpp | 3 ++- test/vm.cpp | 1 + test/vm.h | 1 + 19 files changed, 28 insertions(+), 5 deletions(-) diff --git a/alethzero/OurWebThreeStubServer.h b/alethzero/OurWebThreeStubServer.h index 95cf70438..9420a7cac 100644 --- a/alethzero/OurWebThreeStubServer.h +++ b/alethzero/OurWebThreeStubServer.h @@ -20,6 +20,7 @@ */ #include +#include #include #include #include diff --git a/libethereum/EthereumPeer.h b/libethereum/EthereumPeer.h index 71bfc544f..6f86d7027 100644 --- a/libethereum/EthereumPeer.h +++ b/libethereum/EthereumPeer.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/libp2p/NodeTable.h b/libp2p/NodeTable.h index 23ca33661..f86675662 100644 --- a/libp2p/NodeTable.h +++ b/libp2p/NodeTable.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include "Common.h" diff --git a/libp2p/UDP.h b/libp2p/UDP.h index 5c3b9362f..ff4c2d1c6 100644 --- a/libp2p/UDP.h +++ b/libp2p/UDP.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index f728a29f5..55788c742 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -21,6 +21,7 @@ * @date 2014 */ +#include #include #include #include diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index 6e0db8b47..7515627d7 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -21,6 +21,7 @@ * @date 2014 */ +#include #include #include #include diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 8119ea77a..4df40ae67 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -18,6 +18,7 @@ * Ethereum IDE client. */ +#include #include #include #include diff --git a/mix/Extension.cpp b/mix/Extension.cpp index d4a279afa..df97502d4 100644 --- a/mix/Extension.cpp +++ b/mix/Extension.cpp @@ -17,13 +17,15 @@ * Ethereum IDE client. */ -#include "AppContext.h" + #include #include #include +#include #include #include #include "Extension.h" +#include "AppContext.h" using namespace dev; using namespace dev::mix; diff --git a/test/TestHelper.h b/test/TestHelper.h index 3707a5fff..0b80273c8 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include #include "JsonSpiritHeaders.h" #include diff --git a/test/checkRandomTest.cpp b/test/checkRandomTest.cpp index e3442d438..50c3c367d 100644 --- a/test/checkRandomTest.cpp +++ b/test/checkRandomTest.cpp @@ -20,6 +20,7 @@ * Check a random test and return 0/1 for success or failure. To be used for efficiency in the random test simulation. */ +#include #include #include #include diff --git a/test/createRandomTest.cpp b/test/createRandomTest.cpp index fa5ed7bd3..da1a028bf 100644 --- a/test/createRandomTest.cpp +++ b/test/createRandomTest.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #pragma GCC diagnostic ignored "-Wunused-parameter" diff --git a/test/genesis.cpp b/test/genesis.cpp index 7ca741ee9..a450b79fc 100644 --- a/test/genesis.cpp +++ b/test/genesis.cpp @@ -22,10 +22,14 @@ #include #include + +// Make sure boost/asio.hpp is included before windows.h. +#include +#include + #include "JsonSpiritHeaders.h" #include #include -#include #include "TestHelper.h" using namespace std; diff --git a/test/hexPrefix.cpp b/test/hexPrefix.cpp index 551983db3..c96e9e98c 100644 --- a/test/hexPrefix.cpp +++ b/test/hexPrefix.cpp @@ -21,11 +21,12 @@ */ #include +#include +#include #include "JsonSpiritHeaders.h" #include #include #include -#include #include "TestHelper.h" using namespace std; diff --git a/test/net.cpp b/test/net.cpp index 5039c5436..f842ff1a3 100644 --- a/test/net.cpp +++ b/test/net.cpp @@ -19,6 +19,7 @@ * @date 2014 */ +#include #include #include #include diff --git a/test/rlp.cpp b/test/rlp.cpp index be098d84d..c67f09665 100644 --- a/test/rlp.cpp +++ b/test/rlp.cpp @@ -22,11 +22,12 @@ #include #include +#include +#include #include #include #include #include -#include #include #include "JsonSpiritHeaders.h" #include "TestHelper.h" diff --git a/test/state.cpp b/test/state.cpp index fe133822a..99fa36fc7 100644 --- a/test/state.cpp +++ b/test/state.cpp @@ -20,6 +20,7 @@ * State test functions. */ +#include #include #include #include "JsonSpiritHeaders.h" diff --git a/test/trie.cpp b/test/trie.cpp index 39a3a59a5..a15713412 100644 --- a/test/trie.cpp +++ b/test/trie.cpp @@ -22,12 +22,13 @@ #include #include +#include +#include #include "JsonSpiritHeaders.h" #include #include #include "TrieHash.h" #include "MemTrie.h" -#include #include "TestHelper.h" using namespace std; diff --git a/test/vm.cpp b/test/vm.cpp index 16f7385a0..423d55ac8 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -21,6 +21,7 @@ */ #include +#include #include #include #include diff --git a/test/vm.h b/test/vm.h index 0a5b5fb45..ae28213bd 100644 --- a/test/vm.h +++ b/test/vm.h @@ -25,6 +25,7 @@ along with cpp-ethereum. If not, see . #include #include +#include #include #include #include From 0951b9a9cc2493be5fd0f9870ea69ded603d6dc9 Mon Sep 17 00:00:00 2001 From: jhuntley Date: Wed, 21 Jan 2015 11:02:52 -0500 Subject: [PATCH 47/54] Mingw cmake updates. Make sure Boost_INCLUDE_DIRS is included for each library using boost. When installing libraries, don't forget to copy DLLs, add target 'RUNTIME DESTINATION bin'. --- libdevcore/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index a527aa7b0..03f7547e7 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -44,6 +44,6 @@ elseif (UNIX) target_link_libraries(${EXECUTABLE} ${CMAKE_THREAD_LIBS_INIT}) endif() -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) From 36d44fd7beb20646b9bfae40bd2bccac557425c8 Mon Sep 17 00:00:00 2001 From: jhuntley Date: Wed, 21 Jan 2015 11:04:36 -0500 Subject: [PATCH 48/54] Define comes before standard windows header defines. Added __MINGW32__ define to ensure debug_break is defined for mingw builds. --- libdevcore/debugbreak.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdevcore/debugbreak.h b/libdevcore/debugbreak.h index 57d9d8cde..db7abe660 100644 --- a/libdevcore/debugbreak.h +++ b/libdevcore/debugbreak.h @@ -27,7 +27,7 @@ #ifndef DEBUG_BREAK_H #define DEBUG_BREAK_H -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__MINGW32__) #define debug_break __debugbreak From d51036b3e2e2185655460c4e9cbdba3f5a9946dc Mon Sep 17 00:00:00 2001 From: jhuntley Date: Wed, 21 Jan 2015 11:06:43 -0500 Subject: [PATCH 49/54] Adding comments for #undef per project owner request. --- libsolidity/Token.h | 17 +++++++++++------ libsolidity/Types.h | 2 ++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/libsolidity/Token.h b/libsolidity/Token.h index 2c24f7aff..be6a37e5d 100644 --- a/libsolidity/Token.h +++ b/libsolidity/Token.h @@ -47,6 +47,17 @@ #include #include +#if defined(DELETE) +#undef DELETE +#endif + +// Updates for mingw support. #undef conflicting defines which have been +// repurposed for TOKEN_LIST on windows. +#if defined(__MINGW32__) +#undef IN +#undef CONST +#endif + namespace dev { namespace solidity @@ -65,12 +76,6 @@ namespace solidity // an argument (at any position) for a TOKEN_LIST call. It does // nothing with tokens belonging to the respective category. -#if defined(__MINGW32__) -#undef IN -#undef DELETE -#undef CONST -#endif - #define IGNORE_TOKEN(name, string, precedence) #define TOKEN_LIST(T, K) \ diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 99c083c00..77fc66e9f 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -67,6 +67,8 @@ private: MemberMap m_memberTypes; }; +// Updates for mingw support. #undef conflicting defines which have been +// repurposed for TOKEN_LIST on windows. #if defined(__MINGW32__) #undef VOID #endif From 31f39b5e954223f11d4b29938985133b7ca79cf3 Mon Sep 17 00:00:00 2001 From: jhuntley Date: Wed, 21 Jan 2015 12:21:14 -0500 Subject: [PATCH 50/54] Update to resolve "#error : The macro "DELETE" from windows.h conflicts with this file." on windows vs build. --- libsolidity/Token.h | 2 +- libsolidity/Types.h | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libsolidity/Token.h b/libsolidity/Token.h index be6a37e5d..24b06d16c 100644 --- a/libsolidity/Token.h +++ b/libsolidity/Token.h @@ -53,7 +53,7 @@ // Updates for mingw support. #undef conflicting defines which have been // repurposed for TOKEN_LIST on windows. -#if defined(__MINGW32__) +#if defined(_MSC_VER) || defined(__MINGW32__) #undef IN #undef CONST #endif diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 77fc66e9f..511e5f64f 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -31,6 +31,12 @@ #include #include +// Updates for mingw support. #undef conflicting defines which have been +// repurposed for TOKEN_LIST on windows. +#if defined(_MSC_VER) || defined(__MINGW32__) +#undef VOID +#endif + namespace dev { namespace solidity @@ -67,12 +73,6 @@ private: MemberMap m_memberTypes; }; -// Updates for mingw support. #undef conflicting defines which have been -// repurposed for TOKEN_LIST on windows. -#if defined(__MINGW32__) -#undef VOID -#endif - /** * Abstract base class that forms the root of the type hierarchy. */ From cb62fddd8acf23c17a0d7b6eac40e4d203fe9da6 Mon Sep 17 00:00:00 2001 From: jhuntley Date: Fri, 23 Jan 2015 13:27:56 -0500 Subject: [PATCH 51/54] Consolidating macro resolution to one header file as per project owner request. Added inline comments covering reasons for undef of macros. Resolves issues with problem #832: Adding UndefWindowsMacros.h to handle V8 CPP conflicts in Windows #832 --- libdevcore/UndefMacros.h | 46 ++++++++++++++++++++++++++++++++++++++++ libsolidity/Token.h | 12 +---------- libsolidity/Types.h | 7 +----- 3 files changed, 48 insertions(+), 17 deletions(-) create mode 100644 libdevcore/UndefMacros.h diff --git a/libdevcore/UndefMacros.h b/libdevcore/UndefMacros.h new file mode 100644 index 000000000..91249523b --- /dev/null +++ b/libdevcore/UndefMacros.h @@ -0,0 +1,46 @@ +/* + 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 UndefMacros.h + * @author Lefteris + * @date 2015 + * + * This header should be used to #undef some really evil macros defined by + * windows.h which result in conflict with our libsolidity/Token.h + */ +#pragma once + +#if defined(_MSC_VER) || defined(__MINGW32__) + +#undef DELETE +#undef IN +#undef VOID +#undef THIS +#undef CONST + +// Conflicting define on MinGW in windows.h +// windows.h(19): #define interface struct +#ifdef interface +#undef interface +#endif + +#elif defined(DELETE) || defined(IN) || defined(VOID) || defined(THIS) || defined(CONST) || defined(interface) + +#error "The preceding macros in this header file are reserved for V8's "\ +"TOKEN_LIST. Please add a platform specific define above to undefine "\ +"overlapping macros." + +#endif diff --git a/libsolidity/Token.h b/libsolidity/Token.h index 24b06d16c..19afaee3a 100644 --- a/libsolidity/Token.h +++ b/libsolidity/Token.h @@ -46,17 +46,7 @@ #include #include #include - -#if defined(DELETE) -#undef DELETE -#endif - -// Updates for mingw support. #undef conflicting defines which have been -// repurposed for TOKEN_LIST on windows. -#if defined(_MSC_VER) || defined(__MINGW32__) -#undef IN -#undef CONST -#endif +#include namespace dev { diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 511e5f64f..afecf3c8e 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -30,12 +30,7 @@ #include #include #include - -// Updates for mingw support. #undef conflicting defines which have been -// repurposed for TOKEN_LIST on windows. -#if defined(_MSC_VER) || defined(__MINGW32__) -#undef VOID -#endif +#include namespace dev { From 0bf7d15a5797e95f95895ab329fbd006d8709cad Mon Sep 17 00:00:00 2001 From: jhuntley Date: Mon, 9 Feb 2015 11:31:04 -0500 Subject: [PATCH 52/54] asio.h and windows.h build comments as per request. --- alethzero/MainWin.cpp | 3 + alethzero/MainWin.h | 3 + eth/main.cpp | 3 + libethereum/All.h | 2 + libethereum/Client.h | 3 + libethereum/EthereumHost.h | 3 + libethereum/EthereumPeer.h | 3 + libp2p/Common.h | 3 + libp2p/Host.cpp | 3 + libp2p/Host.h | 3 + libp2p/Network.cpp | 28 +++-- libp2p/NodeTable.h | 15 ++- libp2p/Session.h | 3 + libp2p/UDP.h | 53 ++++---- libweb3jsonrpc/WebThreeStubServer.cpp | 2 + libweb3jsonrpc/WebThreeStubServerBase.cpp | 8 +- libwebthree/WebThree.cpp | 3 + libwebthree/WebThree.h | 5 +- libwhisper/Common.h | 3 + libwhisper/Interface.h | 3 + libwhisper/Message.h | 3 + libwhisper/WhisperHost.h | 3 + libwhisper/WhisperPeer.h | 3 + mix/AppContext.cpp | 2 + mix/AppContext.h | 2 + mix/ClientModel.cpp | 2 + mix/CodeEditorExtensionManager.cpp | 2 + mix/Extension.cpp | 3 + mix/Extension.h | 2 + mix/QContractDefinition.cpp | 3 + neth/main.cpp | 3 + test/TestHelper.cpp | 3 + test/TestHelper.h | 3 + test/checkRandomTest.cpp | 2 + test/createRandomTest.cpp | 3 + test/fork.cpp | 3 + test/hexPrefix.cpp | 7 +- test/net.cpp | 30 ++--- test/rlp.cpp | 145 +++++++++++----------- test/state.cpp | 2 + test/trie.cpp | 3 + test/txTest.cpp | 3 + test/vm.cpp | 7 +- test/vm.h | 3 + test/whisperTopic.cpp | 3 + 45 files changed, 260 insertions(+), 137 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 966d23128..797db6441 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -20,7 +20,10 @@ */ #include + +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index cd0c309b3..5d2e88168 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -26,7 +26,10 @@ #endif #include + +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/eth/main.cpp b/eth/main.cpp index fa164cfda..705307bac 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -25,9 +25,12 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include #include + #include #include #include diff --git a/libethereum/All.h b/libethereum/All.h index adae84843..9c349d372 100644 --- a/libethereum/All.h +++ b/libethereum/All.h @@ -1,6 +1,8 @@ #pragma once +// Make sure boost/asio.hpp is included before windows.h. #include + #include "Account.h" #include "CanonBlockChain.h" #include "Client.h" diff --git a/libethereum/Client.h b/libethereum/Client.h index fbbe9e22c..d8fd8356e 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -27,8 +27,11 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include #include #include diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index 9e2ddf6de..dc61b0637 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -28,7 +28,10 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/libethereum/EthereumPeer.h b/libethereum/EthereumPeer.h index 6f86d7027..f33c9ddea 100644 --- a/libethereum/EthereumPeer.h +++ b/libethereum/EthereumPeer.h @@ -26,7 +26,10 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/libp2p/Common.h b/libp2p/Common.h index ff7ceb215..ddf5f78b8 100644 --- a/libp2p/Common.h +++ b/libp2p/Common.h @@ -27,8 +27,11 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include #include #include diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index adc408324..87df889d2 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -24,8 +24,11 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include #include #include diff --git a/libp2p/Host.h b/libp2p/Host.h index ec59d105f..b15c14055 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -30,7 +30,10 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/libp2p/Network.cpp b/libp2p/Network.cpp index b54395aec..92db18e93 100644 --- a/libp2p/Network.cpp +++ b/libp2p/Network.cpp @@ -26,8 +26,10 @@ #include #endif +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include #include #include @@ -47,7 +49,7 @@ std::vector Network::getInterfaceAddresses() WSAData wsaData; if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) BOOST_THROW_EXCEPTION(NoNetworking()); - + char ac[80]; if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) { @@ -55,7 +57,7 @@ std::vector Network::getInterfaceAddresses() WSACleanup(); BOOST_THROW_EXCEPTION(NoNetworking()); } - + struct hostent* phe = gethostbyname(ac); if (phe == 0) { @@ -63,7 +65,7 @@ std::vector Network::getInterfaceAddresses() WSACleanup(); BOOST_THROW_EXCEPTION(NoNetworking()); } - + for (int i = 0; phe->h_addr_list[i] != 0; ++i) { struct in_addr addr; @@ -73,18 +75,18 @@ std::vector Network::getInterfaceAddresses() if (!isLocalHostAddress(address)) addresses.push_back(address.to_v4()); } - + WSACleanup(); #else ifaddrs* ifaddr; if (getifaddrs(&ifaddr) == -1) BOOST_THROW_EXCEPTION(NoNetworking()); - + for (auto ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (!ifa->ifa_addr || string(ifa->ifa_name) == "lo0") continue; - + if (ifa->ifa_addr->sa_family == AF_INET) { in_addr addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; @@ -103,12 +105,12 @@ std::vector Network::getInterfaceAddresses() addresses.push_back(address); } } - + if (ifaddr!=NULL) freeifaddrs(ifaddr); - + #endif - + return std::move(addresses); } @@ -135,7 +137,7 @@ int Network::tcp4Listen(bi::tcp::acceptor& _acceptor, unsigned short _listenPort // both attempts failed cwarn << "Couldn't start accepting connections on host. Something very wrong with network?\n" << boost::current_exception_diagnostic_information(); } - + // first attempt failed _acceptor.close(); continue; @@ -147,7 +149,7 @@ int Network::tcp4Listen(bi::tcp::acceptor& _acceptor, unsigned short _listenPort bi::tcp::endpoint Network::traverseNAT(std::vector const& _ifAddresses, unsigned short _listenPort, bi::address& o_upnpifaddr) { asserts(_listenPort != 0); - + UPnP* upnp = nullptr; try { @@ -155,7 +157,7 @@ bi::tcp::endpoint Network::traverseNAT(std::vector const& _ifAddres } // let m_upnp continue as null - we handle it properly. catch (NoUPnPDevice) {} - + bi::tcp::endpoint upnpep; if (upnp && upnp->isValid()) { @@ -179,7 +181,7 @@ bi::tcp::endpoint Network::traverseNAT(std::vector const& _ifAddres } else clog(NetWarn) << "Couldn't punch through NAT (or no NAT in place)."; - + if (upnp) delete upnp; } diff --git a/libp2p/NodeTable.h b/libp2p/NodeTable.h index f86675662..a34602189 100644 --- a/libp2p/NodeTable.h +++ b/libp2p/NodeTable.h @@ -1,16 +1,16 @@ /* 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 . */ @@ -23,8 +23,11 @@ #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include #include "Common.h" @@ -94,7 +97,7 @@ inline std::ostream& operator<<(std::ostream& _out, NodeTable const& _nodeTable) * obtain a list of potential nodes to connect to, and, passes events to * Host whenever a node is added or removed to/from the table. * - * Thread-safety is ensured by modifying NodeEntry details via + * Thread-safety is ensured by modifying NodeEntry details via * shared_ptr replacement instead of mutating values. * * NodeTable accepts a port for UDP and will listen to the port on all available @@ -186,7 +189,7 @@ private: static unsigned const s_bucketSize = 16; ///< Denoted by k in [Kademlia]. Number of nodes stored in each bucket. static unsigned const s_alpha = 3; ///< Denoted by \alpha in [Kademlia]. Number of concurrent FindNode requests. - + /// Intervals /* todo: replace boost::posix_time; change constants to upper camelcase */ @@ -361,7 +364,7 @@ struct FindNode: RLPXDatagram h512 target; unsigned expiration; - + void streamRLP(RLPStream& _s) const { _s.appendList(2); _s << target << expiration; } void interpretRLP(bytesConstRef _bytes) { RLP r(_bytes); target = r[0].toHash(); expiration = r[1].toInt(); } }; diff --git a/libp2p/Session.h b/libp2p/Session.h index 2d5b937bf..e50202221 100644 --- a/libp2p/Session.h +++ b/libp2p/Session.h @@ -27,7 +27,10 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/libp2p/UDP.h b/libp2p/UDP.h index ff4c2d1c6..fdccd353e 100644 --- a/libp2p/UDP.h +++ b/libp2p/UDP.h @@ -1,16 +1,16 @@ /* 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 . */ @@ -26,7 +26,10 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include @@ -50,7 +53,7 @@ public: UDPDatagram(bi::udp::endpoint const& _ep): locus(_ep) {} UDPDatagram(bi::udp::endpoint const& _ep, bytes _data): data(_data), locus(_ep) {} bi::udp::endpoint const& endpoint() const { return locus; } - + bytes data; protected: bi::udp::endpoint locus; @@ -98,7 +101,7 @@ struct UDPSocketEvents virtual void onDisconnected(UDPSocketFace*) {}; virtual void onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytesConstRef _packetData) = 0; }; - + /** * @brief UDP Interface * Handler must implement UDPSocketEvents. @@ -112,7 +115,7 @@ class UDPSocket: UDPSocketFace, public std::enable_shared_from_this m_started; ///< Atomically ensure connection is started once. Start cannot occur unless m_started is false. Managed by start and disconnectWithError. std::atomic m_closed; ///< Connection availability. - + UDPSocketEvents& m_host; ///< Interface which owns this socket. bi::udp::endpoint m_endpoint; ///< Endpoint which we listen to. - + Mutex x_sendQ; std::deque m_sendQ; ///< Queue for egress data. std::array m_recvData; ///< Buffer for ingress data. bi::udp::endpoint m_recvEndpoint; ///< Endpoint data was received from. bi::udp::socket m_socket; ///< Boost asio udp socket. - + Mutex x_socketError; ///< Mutex for error which can be set from host or IO thread. boost::system::error_code m_socketError; ///< Set when shut down due to error. }; @@ -157,29 +160,29 @@ void UDPSocket::connect() bool expect = false; if (!m_started.compare_exchange_strong(expect, true)) return; - + m_socket.open(bi::udp::v4()); m_socket.bind(m_endpoint); - + // clear write queue so reconnect doesn't send stale messages Guard l(x_sendQ); m_sendQ.clear(); - + m_closed = false; doRead(); } - + template bool UDPSocket::send(UDPDatagram const& _datagram) { if (m_closed) return false; - + Guard l(x_sendQ); m_sendQ.push_back(_datagram); if (m_sendQ.size() == 1) doWrite(); - + return true; } @@ -188,7 +191,7 @@ void UDPSocket::doRead() { if (m_closed) return; - + auto self(UDPSocket::shared_from_this()); m_socket.async_receive_from(boost::asio::buffer(m_recvData), m_recvEndpoint, [this, self](boost::system::error_code _ec, size_t _len) { @@ -200,13 +203,13 @@ void UDPSocket::doRead() doRead(); }); } - + template void UDPSocket::doWrite() { if (m_closed) return; - + const UDPDatagram& datagram = m_sendQ[0]; auto self(UDPSocket::shared_from_this()); m_socket.async_send_to(boost::asio::buffer(datagram.data), datagram.endpoint(), [this, self](boost::system::error_code _ec, std::size_t) @@ -245,11 +248,11 @@ void UDPSocket::disconnectWithError(boost::system::err bool expected = true; if (!m_started.compare_exchange_strong(expected, false)) return; - + // set m_closed to true to prevent undeliverable egress messages bool wasClosed = m_closed; m_closed = true; - + // close sockets boost::system::error_code ec; m_socket.shutdown(bi::udp::socket::shutdown_both, ec); @@ -261,6 +264,6 @@ void UDPSocket::disconnectWithError(boost::system::err m_host.onDisconnected(this); } - + } } \ No newline at end of file diff --git a/libweb3jsonrpc/WebThreeStubServer.cpp b/libweb3jsonrpc/WebThreeStubServer.cpp index 55788c742..8b24edf38 100644 --- a/libweb3jsonrpc/WebThreeStubServer.cpp +++ b/libweb3jsonrpc/WebThreeStubServer.cpp @@ -21,8 +21,10 @@ * @date 2014 */ +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include #include #include "WebThreeStubServer.h" diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index 7515627d7..f0d8bf6ef 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -21,7 +21,9 @@ * @date 2014 */ +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include @@ -90,7 +92,7 @@ static Json::Value toJson(dev::eth::TransactionSkeleton const& _t) static Json::Value toJson(dev::eth::LocalisedLogEntry const& _e) { Json::Value res; - + res["data"] = jsFromBinary(_e.data); res["address"] = toJS(_e.address); for (auto const& t: _e.topics) @@ -580,7 +582,7 @@ bool WebThreeStubServerBase::shh_post(Json::Value const& _json) // TODO: insert validification hook here. from = m_ids[m.from()]; } - + face()->inject(toSealed(_json, m, from)); return true; } @@ -648,7 +650,7 @@ Json::Value WebThreeStubServerBase::shh_changed(int _id) continue; ret.append(toJson(h, e, m)); } - + return ret; } diff --git a/libwebthree/WebThree.cpp b/libwebthree/WebThree.cpp index 23dbfe0c4..bf8bdc0b3 100644 --- a/libwebthree/WebThree.cpp +++ b/libwebthree/WebThree.cpp @@ -23,8 +23,11 @@ #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include #include #include diff --git a/libwebthree/WebThree.h b/libwebthree/WebThree.h index bcccc150c..242639af4 100644 --- a/libwebthree/WebThree.h +++ b/libwebthree/WebThree.h @@ -25,8 +25,11 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include #include #include @@ -161,7 +164,7 @@ public: /// Stop the network subsystem. void stopNetwork() override { m_net.stop(); } - + /// Is network working? there may not be any peers yet. bool isNetworkStarted() const override { return m_net.isStarted(); } diff --git a/libwhisper/Common.h b/libwhisper/Common.h index 61c92f6eb..b6a67aa51 100644 --- a/libwhisper/Common.h +++ b/libwhisper/Common.h @@ -23,7 +23,10 @@ #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/libwhisper/Interface.h b/libwhisper/Interface.h index 189c3806c..5956bd4cd 100644 --- a/libwhisper/Interface.h +++ b/libwhisper/Interface.h @@ -26,7 +26,10 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/libwhisper/Message.h b/libwhisper/Message.h index 4b457f251..ff553adef 100644 --- a/libwhisper/Message.h +++ b/libwhisper/Message.h @@ -26,7 +26,10 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/libwhisper/WhisperHost.h b/libwhisper/WhisperHost.h index 701f2ef54..7a4eb66f8 100644 --- a/libwhisper/WhisperHost.h +++ b/libwhisper/WhisperHost.h @@ -26,7 +26,10 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/libwhisper/WhisperPeer.h b/libwhisper/WhisperPeer.h index 0a30accc9..6438b4c70 100644 --- a/libwhisper/WhisperPeer.h +++ b/libwhisper/WhisperPeer.h @@ -26,7 +26,10 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/mix/AppContext.cpp b/mix/AppContext.cpp index 513fd3103..187516599 100644 --- a/mix/AppContext.cpp +++ b/mix/AppContext.cpp @@ -22,7 +22,9 @@ * - KeyEventManager */ +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/mix/AppContext.h b/mix/AppContext.h index f7f17ff63..7f421d7d2 100644 --- a/mix/AppContext.h +++ b/mix/AppContext.h @@ -27,7 +27,9 @@ #pragma once +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 4df40ae67..809d2dfd6 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -18,7 +18,9 @@ * Ethereum IDE client. */ +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/mix/CodeEditorExtensionManager.cpp b/mix/CodeEditorExtensionManager.cpp index f81f6648e..86d2ee587 100644 --- a/mix/CodeEditorExtensionManager.cpp +++ b/mix/CodeEditorExtensionManager.cpp @@ -20,7 +20,9 @@ * Ethereum IDE client. */ +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/mix/Extension.cpp b/mix/Extension.cpp index df97502d4..6795593dc 100644 --- a/mix/Extension.cpp +++ b/mix/Extension.cpp @@ -21,7 +21,10 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include "Extension.h" diff --git a/mix/Extension.h b/mix/Extension.h index b42fd99a2..c2b498ce3 100644 --- a/mix/Extension.h +++ b/mix/Extension.h @@ -19,7 +19,9 @@ #pragma once +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include diff --git a/mix/QContractDefinition.cpp b/mix/QContractDefinition.cpp index ca617955c..725d351fc 100644 --- a/mix/QContractDefinition.cpp +++ b/mix/QContractDefinition.cpp @@ -20,7 +20,10 @@ */ #include + +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/neth/main.cpp b/neth/main.cpp index b6ab5a209..844a29c87 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -25,9 +25,12 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include #include + #include #include #include diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 4ee53f88e..16f0d6d10 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -23,8 +23,11 @@ #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include #include #include diff --git a/test/TestHelper.h b/test/TestHelper.h index 0b80273c8..40294b034 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -22,8 +22,11 @@ #pragma once #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include "JsonSpiritHeaders.h" #include #include diff --git a/test/checkRandomTest.cpp b/test/checkRandomTest.cpp index 50c3c367d..f1daaecbf 100644 --- a/test/checkRandomTest.cpp +++ b/test/checkRandomTest.cpp @@ -20,7 +20,9 @@ * Check a random test and return 0/1 for success or failure. To be used for efficiency in the random test simulation. */ +// Make sure boost/asio.hpp is included before windows.h. #include + #include #include #include diff --git a/test/createRandomTest.cpp b/test/createRandomTest.cpp index da1a028bf..140a7fb38 100644 --- a/test/createRandomTest.cpp +++ b/test/createRandomTest.cpp @@ -23,9 +23,12 @@ #include #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include #include + #pragma GCC diagnostic ignored "-Wunused-parameter" #include #include diff --git a/test/fork.cpp b/test/fork.cpp index 934583164..65c5dd3b5 100644 --- a/test/fork.cpp +++ b/test/fork.cpp @@ -19,9 +19,12 @@ * @date 2014 * Tests for different forking behavior */ + +// Make sure boost/asio.hpp is included before windows.h. #include #include #include + #include #include #include diff --git a/test/hexPrefix.cpp b/test/hexPrefix.cpp index c96e9e98c..5875d62f6 100644 --- a/test/hexPrefix.cpp +++ b/test/hexPrefix.cpp @@ -21,8 +21,11 @@ */ #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include "JsonSpiritHeaders.h" #include #include @@ -54,8 +57,8 @@ BOOST_AUTO_TEST_CASE(hexPrefix_test) for (auto& i: o["seq"].get_array()) v.push_back((byte)i.get_int()); auto e = hexPrefixEncode(v, o["term"].get_bool()); - BOOST_REQUIRE( ! o["out"].is_null() ); - BOOST_CHECK( o["out"].get_str() == toHex(e) ); + BOOST_REQUIRE( ! o["out"].is_null() ); + BOOST_CHECK( o["out"].get_str() == toHex(e) ); } } diff --git a/test/net.cpp b/test/net.cpp index f842ff1a3..fafcc1ff6 100644 --- a/test/net.cpp +++ b/test/net.cpp @@ -19,8 +19,10 @@ * @date 2014 */ +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include #include #include @@ -44,7 +46,7 @@ public: void start() { startWorking(); } void doWork() { m_io.run(); } void doneWorking() { m_io.reset(); m_io.poll(); m_io.reset(); } - + protected: ba::io_service m_io; }; @@ -53,23 +55,23 @@ struct TestNodeTable: public NodeTable { /// Constructor TestNodeTable(ba::io_service& _io, KeyPair _alias, uint16_t _port = 30300): NodeTable(_io, _alias, _port) {} - + static std::vector> createTestNodes(unsigned _count) { std::vector> ret; asserts(_count < 1000); static uint16_t s_basePort = 30500; - + ret.clear(); for (unsigned i = 0; i < _count; i++) { KeyPair k = KeyPair::create(); ret.push_back(make_pair(k,s_basePort+i)); } - + return std::move(ret); } - + void pingTestNodes(std::vector> const& _testNodes) { bi::address ourIp = bi::address::from_string("127.0.0.1"); @@ -79,7 +81,7 @@ struct TestNodeTable: public NodeTable this_thread::sleep_for(chrono::milliseconds(2)); } } - + void populateTestNodes(std::vector> const& _testNodes, size_t _count = 0) { if (!_count) @@ -92,7 +94,7 @@ struct TestNodeTable: public NodeTable else break; } - + void reset() { Guard l(x_state); @@ -109,13 +111,13 @@ struct TestNodeTableHost: public TestHost ~TestNodeTableHost() { m_io.stop(); stopWorking(); } void setup() { for (auto n: testNodes) nodeTables.push_back(make_shared(m_io,n.first,n.second)); } - + void pingAll() { for (auto& t: nodeTables) t->pingTestNodes(testNodes); } - + void populateAll(size_t _count = 0) { for (auto& t: nodeTables) t->populateTestNodes(testNodes, _count); } - + void populate(size_t _count = 0) { nodeTable->populateTestNodes(testNodes, _count); } - + KeyPair m_alias; shared_ptr nodeTable; std::vector> testNodes; // keypair and port @@ -131,7 +133,7 @@ public: void onReceived(UDPSocketFace*, bi::udp::endpoint const&, bytesConstRef _packet) { if (_packet.toString() == "AAAA") success = true; } shared_ptr> m_socket; - + bool success = false; }; @@ -140,7 +142,7 @@ BOOST_AUTO_TEST_CASE(test_neighbours_packet) KeyPair k = KeyPair::create(); std::vector> testNodes(TestNodeTable::createTestNodes(16)); bi::udp::endpoint to(boost::asio::ip::address::from_string("127.0.0.1"), 30000); - + Neighbours out(to); for (auto n: testNodes) { @@ -187,7 +189,7 @@ BOOST_AUTO_TEST_CASE(kademlia) node.setup(); node.populate(); clog << "NodeTable:\n" << *node.nodeTable.get() << endl; - + node.populateAll(); clog << "NodeTable:\n" << *node.nodeTable.get() << endl; diff --git a/test/rlp.cpp b/test/rlp.cpp index c67f09665..fc4f858ed 100644 --- a/test/rlp.cpp +++ b/test/rlp.cpp @@ -22,8 +22,11 @@ #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include #include #include @@ -67,76 +70,76 @@ namespace dev testPath += "/BasicTests"; string s = asString(contents(testPath + "/rlptest.json")); - BOOST_REQUIRE_MESSAGE( s.length() > 0, - "Contents of 'rlptest.json' is empty. Have you cloned the 'tests' repo branch develop?"); + BOOST_REQUIRE_MESSAGE( s.length() > 0, + "Contents of 'rlptest.json' is empty. Have you cloned the 'tests' repo branch develop?"); js::read_string(s, v); - } + } static void checkRLPTestCase(js::mObject& o) - { - BOOST_REQUIRE( o.count("in") > 0 ); - BOOST_REQUIRE( o.count("out") > 0 ); - BOOST_REQUIRE(!o["out"].is_null()); - } + { + BOOST_REQUIRE( o.count("in") > 0 ); + BOOST_REQUIRE( o.count("out") > 0 ); + BOOST_REQUIRE(!o["out"].is_null()); + } static void checkRLPAgainstJson(js::mValue& v, RLP& u) { - if ( v.type() == js::str_type ) - { + if ( v.type() == js::str_type ) + { const std::string& expectedText = v.get_str(); - if ( !expectedText.empty() && expectedText.front() == '#' ) - { - // Deal with bigint instead of a raw string - std::string bigIntStr = expectedText.substr(1,expectedText.length()-1); - std::stringstream bintStream(bigIntStr); - bigint val; - bintStream >> val; - BOOST_CHECK( !u.isList() ); + if ( !expectedText.empty() && expectedText.front() == '#' ) + { + // Deal with bigint instead of a raw string + std::string bigIntStr = expectedText.substr(1,expectedText.length()-1); + std::stringstream bintStream(bigIntStr); + bigint val; + bintStream >> val; + BOOST_CHECK( !u.isList() ); BOOST_CHECK( !u.isNull() ); BOOST_CHECK( u ); // operator bool() - BOOST_CHECK(u == val); - } - else - { - BOOST_CHECK( !u.isList() ); - BOOST_CHECK( !u.isNull() ); - BOOST_CHECK( u.isData() ); - BOOST_CHECK( u ); - BOOST_CHECK( u.size() == expectedText.length() ); - BOOST_CHECK(u == expectedText); + BOOST_CHECK(u == val); } - } - else if ( v.type() == js::int_type ) - { - const int expectedValue = v.get_int(); - BOOST_CHECK( u.isInt() ); - BOOST_CHECK( !u.isList() ); + else + { + BOOST_CHECK( !u.isList() ); + BOOST_CHECK( !u.isNull() ); + BOOST_CHECK( u.isData() ); + BOOST_CHECK( u ); + BOOST_CHECK( u.size() == expectedText.length() ); + BOOST_CHECK(u == expectedText); + } + } + else if ( v.type() == js::int_type ) + { + const int expectedValue = v.get_int(); + BOOST_CHECK( u.isInt() ); + BOOST_CHECK( !u.isList() ); BOOST_CHECK( !u.isNull() ); BOOST_CHECK( u ); // operator bool() - BOOST_CHECK(u == expectedValue); - } - else if ( v.type() == js::array_type ) - { - BOOST_CHECK( u.isList() ); - BOOST_CHECK( !u.isInt() ); - BOOST_CHECK( !u.isData() ); - js::mArray& arr = v.get_array(); - BOOST_CHECK( u.itemCount() == arr.size() ); - unsigned i; - for( i = 0; i < arr.size(); i++ ) - { - RLP item = u[i]; - checkRLPAgainstJson(arr[i], item); - } - } - else - { + BOOST_CHECK(u == expectedValue); + } + else if ( v.type() == js::array_type ) + { + BOOST_CHECK( u.isList() ); + BOOST_CHECK( !u.isInt() ); + BOOST_CHECK( !u.isData() ); + js::mArray& arr = v.get_array(); + BOOST_CHECK( u.itemCount() == arr.size() ); + unsigned i; + for( i = 0; i < arr.size(); i++ ) + { + RLP item = u[i]; + checkRLPAgainstJson(arr[i], item); + } + } + else + { BOOST_ERROR("Invalid Javascript object!"); - } - - } + } + + } } -} +} BOOST_AUTO_TEST_SUITE(BasicTests) @@ -155,30 +158,30 @@ BOOST_AUTO_TEST_CASE(rlp_encoding_test) RLPStream s; dev::test::buildRLP(o["in"], s); - std::string expectedText(o["out"].get_str()); - std::transform(expectedText.begin(), expectedText.end(), expectedText.begin(), ::tolower ); + std::string expectedText(o["out"].get_str()); + std::transform(expectedText.begin(), expectedText.end(), expectedText.begin(), ::tolower ); - const std::string& computedText = toHex(s.out()); + const std::string& computedText = toHex(s.out()); - std::stringstream msg; + std::stringstream msg; msg << "Encoding Failed: expected: " << expectedText << std::endl; - msg << " But Computed: " << computedText; + msg << " But Computed: " << computedText; BOOST_CHECK_MESSAGE( - expectedText == computedText, + expectedText == computedText, msg.str() - ); + ); } } BOOST_AUTO_TEST_CASE(rlp_decoding_test) { - cnote << "Testing RLP decoding..."; - // Uses the same test cases as encoding but in reverse. - // We read into the string of hex values, convert to bytes, - // and then compare the output structure to the json of the - // input object. + cnote << "Testing RLP decoding..."; + // Uses the same test cases as encoding but in reverse. + // We read into the string of hex values, convert to bytes, + // and then compare the output structure to the json of the + // input object. js::mValue v; dev::test::getRLPTestCases(v); for (auto& i: v.get_obj()) @@ -186,11 +189,11 @@ BOOST_AUTO_TEST_CASE(rlp_decoding_test) js::mObject& o = i.second.get_obj(); cnote << i.first; dev::test::checkRLPTestCase(o); - + js::mValue& inputData = o["in"]; - bytes payloadToDecode = fromHex(o["out"].get_str()); + bytes payloadToDecode = fromHex(o["out"].get_str()); - RLP payload(payloadToDecode); + RLP payload(payloadToDecode); dev::test::checkRLPAgainstJson(inputData, payload); diff --git a/test/state.cpp b/test/state.cpp index 99fa36fc7..e2201f241 100644 --- a/test/state.cpp +++ b/test/state.cpp @@ -20,9 +20,11 @@ * State test functions. */ +// Make sure boost/asio.hpp is included before windows.h. #include #include #include + #include "JsonSpiritHeaders.h" #include #include diff --git a/test/trie.cpp b/test/trie.cpp index a15713412..312749752 100644 --- a/test/trie.cpp +++ b/test/trie.cpp @@ -22,8 +22,11 @@ #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include "JsonSpiritHeaders.h" #include #include diff --git a/test/txTest.cpp b/test/txTest.cpp index dcb2515af..3f67c0a2f 100644 --- a/test/txTest.cpp +++ b/test/txTest.cpp @@ -19,9 +19,12 @@ * @date 2014 * Simple peer transaction send test. */ + +// Make sure boost/asio.hpp is included before windows.h. #include #include #include + #include #include #include diff --git a/test/vm.cpp b/test/vm.cpp index 423d55ac8..00ba82aaf 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -21,8 +21,11 @@ */ #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include #include #include "vm.h" @@ -287,7 +290,7 @@ eth::OnOpFunc FakeExtVM::simpleTrace() /*add the storage*/ Object storage; for (auto const& i: std::get<2>(ext.addresses.find(ext.myAddress)->second)) - storage.push_back(Pair( (string)i.first , (string)i.second)); + storage.push_back(Pair( (string)i.first , (string)i.second)); /*add all the other details*/ o_step.push_back(Pair("storage", storage)); @@ -366,7 +369,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) auto argc = boost::unit_test::framework::master_test_suite().argc; auto argv = boost::unit_test::framework::master_test_suite().argv; for (auto i = 0; i < argc; ++i) - { + { if (std::string(argv[i]) == "--show-times") { auto testDuration = endTime - startTime; diff --git a/test/vm.h b/test/vm.h index ae28213bd..03b3b4e5e 100644 --- a/test/vm.h +++ b/test/vm.h @@ -25,8 +25,11 @@ along with cpp-ethereum. If not, see . #include #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include #include #include diff --git a/test/whisperTopic.cpp b/test/whisperTopic.cpp index 2f90b4fb9..0937ab922 100644 --- a/test/whisperTopic.cpp +++ b/test/whisperTopic.cpp @@ -19,8 +19,11 @@ * @date 2014 */ #include + +// Make sure boost/asio.hpp is included before windows.h. #include #include + #include #include #include From 15810eb55fc6b60fc712cfe1c32ec253909b2c65 Mon Sep 17 00:00:00 2001 From: jhuntley Date: Thu, 26 Feb 2015 15:52:02 -0500 Subject: [PATCH 53/54] cmake build updates for mingw. Make sure to include boost where referenced and install runtime dlls to bin upon install. --- eth/CMakeLists.txt | 2 +- libnatspec/CMakeLists.txt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index bc458a50f..68ee8c775 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -28,7 +28,7 @@ endif() target_link_libraries(${EXECUTABLE} webthree) target_link_libraries(${EXECUTABLE} secp256k1) -if (WIN32) +if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW) add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND ${CMAKE_COMMAND} ARGS -E copy ${MHD_DLL_RELEASE} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") endif() diff --git a/libnatspec/CMakeLists.txt b/libnatspec/CMakeLists.txt index af15d56a9..d8d9d46ec 100644 --- a/libnatspec/CMakeLists.txt +++ b/libnatspec/CMakeLists.txt @@ -14,6 +14,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) include_directories(BEFORE ..) +include_directories(${Boost_INCLUDE_DIRS}) set(EXECUTABLE natspec) @@ -31,5 +32,5 @@ target_link_libraries(${EXECUTABLE} Qt5::Core) target_link_libraries(${EXECUTABLE} Qt5::Qml) target_link_libraries(${EXECUTABLE} devcore) -install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) +install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib ) install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} ) From 6d62e3ab26f1dc980ebe8475817f6982b1bac195 Mon Sep 17 00:00:00 2001 From: jhuntley Date: Thu, 26 Feb 2015 16:05:53 -0500 Subject: [PATCH 54/54] Revert all asio.h includes except for in 2 files, DebuggingStateWrapper.h and Transact.cpp. After enabling WIN32_LEAN_AND_MEAN, all the asio.h include issues, commit 20b6e24ffcab088e71092e07030a377d3135da3c, went away. --- alethzero/MainWin.h | 3 -- alethzero/OurWebThreeStubServer.h | 1 - alethzero/Transact.cpp | 3 ++ eth/main.cpp | 2 - libethereum/All.h | 3 -- libethereum/Client.h | 2 - libethereum/EthereumHost.h | 3 -- libp2p/Host.cpp | 2 - libp2p/Host.h | 3 -- libp2p/Network.cpp | 2 - libp2p/NodeTable.h | 84 +++++++++++++++--------------- libp2p/Session.h | 5 +- libp2p/UDP.h | 5 +- libwebthree/WebThree.cpp | 2 - libwhisper/Common.h | 3 -- libwhisper/Interface.h | 3 -- libwhisper/Message.h | 3 -- libwhisper/WhisperHost.h | 3 -- libwhisper/WhisperPeer.h | 3 -- mix/AppContext.cpp | 3 -- mix/AppContext.h | 3 -- mix/CodeEditorExtensionManager.cpp | 3 -- mix/DebuggingStateWrapper.h | 3 ++ mix/Extension.cpp | 3 -- mix/Extension.h | 3 -- mix/QContractDefinition.cpp | 3 -- neth/main.cpp | 2 - test/TestHelper.cpp | 2 - test/TestHelper.h | 2 - test/checkRandomTest.cpp | 3 -- test/createRandomTest.cpp | 2 - test/fork.cpp | 2 - test/genesis.cpp | 4 +- test/hexPrefix.cpp | 2 - test/net.cpp | 10 ++-- test/rlp.cpp | 2 - test/state.cpp | 2 - test/trie.cpp | 2 - test/txTest.cpp | 2 - test/vm.cpp | 2 - test/vm.h | 2 - test/whisperTopic.cpp | 32 ++++++------ third/MainWin.cpp | 2 - 43 files changed, 69 insertions(+), 162 deletions(-) diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 5d2e88168..0a2b3461e 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -27,9 +27,6 @@ #include -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include diff --git a/alethzero/OurWebThreeStubServer.h b/alethzero/OurWebThreeStubServer.h index 9420a7cac..95cf70438 100644 --- a/alethzero/OurWebThreeStubServer.h +++ b/alethzero/OurWebThreeStubServer.h @@ -20,7 +20,6 @@ */ #include -#include #include #include #include diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index c59c80c39..df6c5258d 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -19,6 +19,9 @@ * @date 2015 */ +// Make sure boost/asio.hpp is included before windows.h. +#include + #include "Transact.h" #include diff --git a/eth/main.cpp b/eth/main.cpp index 705307bac..e3753364f 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -26,8 +26,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include diff --git a/libethereum/All.h b/libethereum/All.h index 9c349d372..24109cb87 100644 --- a/libethereum/All.h +++ b/libethereum/All.h @@ -1,8 +1,5 @@ #pragma once -// Make sure boost/asio.hpp is included before windows.h. -#include - #include "Account.h" #include "CanonBlockChain.h" #include "Client.h" diff --git a/libethereum/Client.h b/libethereum/Client.h index d8fd8356e..5fabca10b 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -28,8 +28,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index dc61b0637..0f06230ff 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -29,9 +29,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 87df889d2..ed0ee653e 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -25,8 +25,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include diff --git a/libp2p/Host.h b/libp2p/Host.h index b15c14055..ce4dfa50c 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -31,9 +31,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include diff --git a/libp2p/Network.cpp b/libp2p/Network.cpp index 92db18e93..d004f33d2 100644 --- a/libp2p/Network.cpp +++ b/libp2p/Network.cpp @@ -26,8 +26,6 @@ #include #endif -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include diff --git a/libp2p/NodeTable.h b/libp2p/NodeTable.h index a34602189..10fa921e4 100644 --- a/libp2p/NodeTable.h +++ b/libp2p/NodeTable.h @@ -24,8 +24,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include @@ -58,7 +56,7 @@ class NodeTableEventHandler friend class NodeTable; public: virtual void processEvent(NodeId const& _n, NodeTableEventType const& _e) = 0; - + protected: /// Called by NodeTable on behalf of an implementation (Host) to process new events without blocking nodetable. void processEvents() @@ -77,10 +75,10 @@ protected: for (auto const& e: events) processEvent(e.first, e.second); } - + /// Called by NodeTable to append event. virtual void appendEvent(NodeId _n, NodeTableEventType _e) { Guard l(x_events); m_nodeEventHandler.push_back(_n); m_events[_n] = _e; } - + Mutex x_events; std::list m_nodeEventHandler; std::map m_events; @@ -88,10 +86,10 @@ protected: class NodeTable; inline std::ostream& operator<<(std::ostream& _out, NodeTable const& _nodeTable); - + /** * NodeTable using modified kademlia for node discovery and preference. - * Node table requires an IO service, creates a socket for incoming + * Node table requires an IO service, creates a socket for incoming * UDP messages and implements a kademlia-like protocol. Node requests and * responses are used to build a node table which can be queried to * obtain a list of potential nodes to connect to, and, passes events to @@ -134,69 +132,69 @@ class NodeTable: UDPSocketEvents, public std::enable_shared_from_this using NodeSocket = UDPSocket; using TimePoint = std::chrono::steady_clock::time_point; using EvictionTimeout = std::pair, NodeId>; ///< First NodeId may be evicted and replaced with second NodeId. - + public: NodeTable(ba::io_service& _io, KeyPair _alias, uint16_t _udpPort = 30303); ~NodeTable(); - + /// Returns distance based on xor metric two node ids. Used by NodeEntry and NodeTable. static unsigned distance(NodeId const& _a, NodeId const& _b) { u512 d = _a ^ _b; unsigned ret; for (ret = 0; d >>= 1; ++ret) {}; return ret; } - + /// Set event handler for NodeEntryAdded and NodeEntryRemoved events. void setEventHandler(NodeTableEventHandler* _handler) { m_nodeEventHandler.reset(_handler); } - + /// Called by implementation which provided handler to process NodeEntryAdded/NodeEntryRemoved events. Events are coalesced by type whereby old events are ignored. void processEvents(); - + /// Add node. Node will be pinged if it's not already known. std::shared_ptr addNode(Public const& _pubk, bi::udp::endpoint const& _udp, bi::tcp::endpoint const& _tcp); - + /// Add node. Node will be pinged if it's not already known. std::shared_ptr addNode(Node const& _node); /// To be called when node table is empty. Runs node discovery with m_node.id as the target in order to populate node-table. void discover(); - + /// Returns list of node ids active in node table. std::list nodes() const; - + /// Returns node count. unsigned count() const { return m_nodes.size(); } - + /// Returns snapshot of table. std::list snapshot() const; - + /// Returns true if node id is in node table. bool haveNode(NodeId const& _id) { Guard l(x_nodes); return m_nodes.count(_id) > 0; } - + /// Returns the Node to the corresponding node id or the empty Node if that id is not found. Node node(NodeId const& _id); - + #if defined(BOOST_AUTO_TEST_SUITE) || defined(_MSC_VER) // MSVC includes access specifier in symbol name protected: #else private: #endif - + /// Constants for Kademlia, derived from address space. - + static unsigned const s_addressByteSize = sizeof(NodeId); ///< Size of address type in bytes. static unsigned const s_bits = 8 * s_addressByteSize; ///< Denoted by n in [Kademlia]. static unsigned const s_bins = s_bits - 1; ///< Size of m_state (excludes root, which is us). static unsigned const s_maxSteps = boost::static_log2::value; ///< Max iterations of discovery. (discover) - + /// Chosen constants - + static unsigned const s_bucketSize = 16; ///< Denoted by k in [Kademlia]. Number of nodes stored in each bucket. static unsigned const s_alpha = 3; ///< Denoted by \alpha in [Kademlia]. Number of concurrent FindNode requests. /// Intervals - + /* 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::seconds const c_bucketRefresh = std::chrono::seconds(3600); ///< Refresh interval prevents bucket from becoming stale. [Kademlia] - + struct NodeBucket { unsigned distance; @@ -204,50 +202,50 @@ private: std::list> nodes; void touch() { modified = std::chrono::steady_clock::now(); } }; - + /// Used to ping endpoint. void ping(bi::udp::endpoint _to) const; - + /// Used ping known node. Used by node table when refreshing buckets and as part of eviction process (see evict). void ping(NodeEntry* _n) const; - + /// 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.udp); } - + /// Used by asynchronous operations to return NodeEntry which is active and managed by node table. std::shared_ptr nodeEntry(NodeId _id); - + /// Used to discovery nodes on network which are close to the given target. /// Sends s_alpha concurrent requests to nodes nearest to target, for nodes nearest to target, up to s_maxSteps rounds. void discover(NodeId _target, unsigned _round = 0, std::shared_ptr>> _tried = std::shared_ptr>>()); /// Returns nodes from node table which are closest to target. std::vector> nearestNodeEntries(NodeId _target); - + /// Asynchronously drops _leastSeen node if it doesn't reply and adds _new node, otherwise _new node is thrown away. void evict(std::shared_ptr _leastSeen, std::shared_ptr _new); - + /// Called whenever activity is received from an unknown node in order to maintain node table. void noteActiveNode(Public const& _pubk, bi::udp::endpoint const& _endpoint); /// Used to drop node when timeout occurs or when evict() result is to keep previous node. void dropNode(std::shared_ptr _n); - + /// Returns references to bucket which corresponds to distance of node id. /// @warning Only use the return reference locked x_state mutex. // TODO p2p: Remove this method after removing offset-by-one functionality. NodeBucket& bucket_UNSAFE(NodeEntry const* _n); /// General Network Events - + /// Called by m_socket when packet is received. void onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytesConstRef _packet); - + /// Called by m_socket when socket is disconnected. void onDisconnected(UDPSocketFace*) {} - + /// Tasks - + /// Called by evict() to ensure eviction check is scheduled to run and terminates when no evictions remain. Asynchronous. void doCheckEvictions(boost::system::error_code const& _ec); @@ -255,7 +253,7 @@ private: void doRefreshBuckets(boost::system::error_code const& _ec); std::unique_ptr m_nodeEventHandler; ///< Event handler for node events. - + Node m_node; ///< This node. Secret m_secret; ///< This nodes secret key. @@ -312,7 +310,7 @@ struct PingNode: RLPXDatagram PingNode(bi::udp::endpoint _ep, std::string _src, uint16_t _srcPort, std::chrono::seconds _expiration = std::chrono::seconds(60)): RLPXDatagram(_ep), ipAddress(_src), port(_srcPort), expiration(futureFromEpoch(_expiration)) {} static const uint8_t type = 1; - + unsigned version = 1; std::string ipAddress; unsigned port; @@ -337,7 +335,7 @@ struct Pong: RLPXDatagram h256 echo; ///< MCD of PingNode unsigned expiration; - + void streamRLP(RLPStream& _s) const { _s.appendList(2); _s << echo << expiration; } void interpretRLP(bytesConstRef _bytes) { RLP r(_bytes); echo = (h256)r[0]; expiration = r[1].toInt(); } }; @@ -361,7 +359,7 @@ struct FindNode: RLPXDatagram FindNode(bi::udp::endpoint _ep, NodeId _target, std::chrono::seconds _expiration = std::chrono::seconds(30)): RLPXDatagram(_ep), target(_target), expiration(futureFromEpoch(_expiration)) {} static const uint8_t type = 3; - + h512 target; unsigned expiration; @@ -387,7 +385,7 @@ struct Neighbours: RLPXDatagram void streamRLP(RLPStream& _s) const { _s.appendList(3); _s << ipAddress << port << node; } void interpretRLP(RLP const& _r) { ipAddress = _r[0].toString(); port = _r[1].toInt(); node = h512(_r[2].toBytes()); } }; - + Neighbours(bi::udp::endpoint _ep): RLPXDatagram(_ep), expiration(futureFromEpoch(std::chrono::seconds(30))) {} Neighbours(bi::udp::endpoint _to, std::vector> const& _nearest, unsigned _offset = 0, unsigned _limit = 0): RLPXDatagram(_to), expiration(futureFromEpoch(std::chrono::seconds(30))) { @@ -401,7 +399,7 @@ struct Neighbours: RLPXDatagram nodes.push_back(node); } } - + static const uint8_t type = 4; std::vector nodes; unsigned expiration = 1; diff --git a/libp2p/Session.h b/libp2p/Session.h index e50202221..a5347cddb 100644 --- a/libp2p/Session.h +++ b/libp2p/Session.h @@ -28,9 +28,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include @@ -116,7 +113,7 @@ private: bool m_dropped = false; ///< If true, we've already divested ourselves of this peer. We're just waiting for the reads & writes to fail before the shared_ptr goes OOS and the destructor kicks in. PeerSessionInfo m_info; ///< Dynamic information about this peer. - + bool m_theyRequestedNodes = false; ///< Has the peer requested nodes from us without receiveing an answer from us? bool m_weRequestedNodes = false; ///< Have we requested nodes from the peer and not received an answer yet? diff --git a/libp2p/UDP.h b/libp2p/UDP.h index fdccd353e..3c3399acb 100644 --- a/libp2p/UDP.h +++ b/libp2p/UDP.h @@ -27,9 +27,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include @@ -67,7 +64,7 @@ struct RLPXDatagramFace: public UDPDatagram static uint64_t futureFromEpoch(std::chrono::milliseconds _ms) { return std::chrono::duration_cast((std::chrono::system_clock::now() + _ms).time_since_epoch()).count(); } static uint64_t futureFromEpoch(std::chrono::seconds _sec) { return std::chrono::duration_cast((std::chrono::system_clock::now() + _sec).time_since_epoch()).count(); } static Public authenticate(bytesConstRef _sig, bytesConstRef _rlp); - + virtual uint8_t packetType() = 0; RLPXDatagramFace(bi::udp::endpoint const& _ep): UDPDatagram(_ep) {} virtual h256 sign(Secret const& _from); diff --git a/libwebthree/WebThree.cpp b/libwebthree/WebThree.cpp index bf8bdc0b3..6c6414741 100644 --- a/libwebthree/WebThree.cpp +++ b/libwebthree/WebThree.cpp @@ -24,8 +24,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include diff --git a/libwhisper/Common.h b/libwhisper/Common.h index b6a67aa51..480b79350 100644 --- a/libwhisper/Common.h +++ b/libwhisper/Common.h @@ -24,9 +24,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include diff --git a/libwhisper/Interface.h b/libwhisper/Interface.h index 5956bd4cd..db595e21e 100644 --- a/libwhisper/Interface.h +++ b/libwhisper/Interface.h @@ -27,9 +27,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include diff --git a/libwhisper/Message.h b/libwhisper/Message.h index ff553adef..bd73df268 100644 --- a/libwhisper/Message.h +++ b/libwhisper/Message.h @@ -27,9 +27,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include diff --git a/libwhisper/WhisperHost.h b/libwhisper/WhisperHost.h index 7a4eb66f8..ebbbcf8ed 100644 --- a/libwhisper/WhisperHost.h +++ b/libwhisper/WhisperHost.h @@ -27,9 +27,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include diff --git a/libwhisper/WhisperPeer.h b/libwhisper/WhisperPeer.h index 6438b4c70..8542e987d 100644 --- a/libwhisper/WhisperPeer.h +++ b/libwhisper/WhisperPeer.h @@ -27,9 +27,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include diff --git a/mix/AppContext.cpp b/mix/AppContext.cpp index 187516599..29124a39a 100644 --- a/mix/AppContext.cpp +++ b/mix/AppContext.cpp @@ -22,9 +22,6 @@ * - KeyEventManager */ -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include diff --git a/mix/AppContext.h b/mix/AppContext.h index 7f421d7d2..268771207 100644 --- a/mix/AppContext.h +++ b/mix/AppContext.h @@ -27,9 +27,6 @@ #pragma once -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include diff --git a/mix/CodeEditorExtensionManager.cpp b/mix/CodeEditorExtensionManager.cpp index 86d2ee587..97b808eb2 100644 --- a/mix/CodeEditorExtensionManager.cpp +++ b/mix/CodeEditorExtensionManager.cpp @@ -20,9 +20,6 @@ * Ethereum IDE client. */ -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 2645e8c5a..7a34d6493 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -22,6 +22,9 @@ #pragma once +// Make sure boost/asio.hpp is included before windows.h. +#include + #include #include #include diff --git a/mix/Extension.cpp b/mix/Extension.cpp index 6795593dc..eae842279 100644 --- a/mix/Extension.cpp +++ b/mix/Extension.cpp @@ -22,9 +22,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include "Extension.h" diff --git a/mix/Extension.h b/mix/Extension.h index c2b498ce3..98daf2918 100644 --- a/mix/Extension.h +++ b/mix/Extension.h @@ -19,9 +19,6 @@ #pragma once -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include diff --git a/mix/QContractDefinition.cpp b/mix/QContractDefinition.cpp index 725d351fc..27779ce11 100644 --- a/mix/QContractDefinition.cpp +++ b/mix/QContractDefinition.cpp @@ -21,9 +21,6 @@ #include -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include diff --git a/neth/main.cpp b/neth/main.cpp index 844a29c87..8228f2770 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -26,8 +26,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 16f0d6d10..82add295e 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -24,8 +24,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include diff --git a/test/TestHelper.h b/test/TestHelper.h index 40294b034..6f9143c5c 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -23,8 +23,6 @@ #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include "JsonSpiritHeaders.h" diff --git a/test/checkRandomTest.cpp b/test/checkRandomTest.cpp index f1daaecbf..e3442d438 100644 --- a/test/checkRandomTest.cpp +++ b/test/checkRandomTest.cpp @@ -20,9 +20,6 @@ * Check a random test and return 0/1 for success or failure. To be used for efficiency in the random test simulation. */ -// Make sure boost/asio.hpp is included before windows.h. -#include - #include #include #include diff --git a/test/createRandomTest.cpp b/test/createRandomTest.cpp index 140a7fb38..55e023759 100644 --- a/test/createRandomTest.cpp +++ b/test/createRandomTest.cpp @@ -24,8 +24,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include diff --git a/test/fork.cpp b/test/fork.cpp index 65c5dd3b5..a2eb6f4eb 100644 --- a/test/fork.cpp +++ b/test/fork.cpp @@ -20,8 +20,6 @@ * Tests for different forking behavior */ -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include diff --git a/test/genesis.cpp b/test/genesis.cpp index a450b79fc..5ac3ea2a8 100644 --- a/test/genesis.cpp +++ b/test/genesis.cpp @@ -23,8 +23,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include "JsonSpiritHeaders.h" @@ -44,7 +42,7 @@ BOOST_AUTO_TEST_CASE(emptySHA3Types) { h256 emptyListSHA3(fromHex("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")); BOOST_REQUIRE_EQUAL(emptyListSHA3, EmptyListSHA3); - + h256 emptySHA3(fromHex("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); BOOST_REQUIRE_EQUAL(emptySHA3, EmptySHA3); } diff --git a/test/hexPrefix.cpp b/test/hexPrefix.cpp index 5875d62f6..da294ba5b 100644 --- a/test/hexPrefix.cpp +++ b/test/hexPrefix.cpp @@ -22,8 +22,6 @@ #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include "JsonSpiritHeaders.h" diff --git a/test/net.cpp b/test/net.cpp index fafcc1ff6..831c283e2 100644 --- a/test/net.cpp +++ b/test/net.cpp @@ -19,8 +19,6 @@ * @date 2014 */ -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include @@ -192,22 +190,22 @@ BOOST_AUTO_TEST_CASE(kademlia) node.populateAll(); clog << "NodeTable:\n" << *node.nodeTable.get() << endl; - + auto nodes = node.nodeTable->nodes(); nodes.sort(); - + node.nodeTable->reset(); clog << "NodeTable:\n" << *node.nodeTable.get() << endl; node.populate(1); clog << "NodeTable:\n" << *node.nodeTable.get() << endl; - + node.nodeTable->discover(); this_thread::sleep_for(chrono::milliseconds(2000)); clog << "NodeTable:\n" << *node.nodeTable.get() << endl; BOOST_REQUIRE_EQUAL(node.nodeTable->count(), 8); - + auto netNodes = node.nodeTable->nodes(); netNodes.sort(); diff --git a/test/rlp.cpp b/test/rlp.cpp index fc4f858ed..9062b54f4 100644 --- a/test/rlp.cpp +++ b/test/rlp.cpp @@ -23,8 +23,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include diff --git a/test/state.cpp b/test/state.cpp index e2201f241..17ebe2b77 100644 --- a/test/state.cpp +++ b/test/state.cpp @@ -20,8 +20,6 @@ * State test functions. */ -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include diff --git a/test/trie.cpp b/test/trie.cpp index 312749752..dd335b4a6 100644 --- a/test/trie.cpp +++ b/test/trie.cpp @@ -23,8 +23,6 @@ #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include "JsonSpiritHeaders.h" diff --git a/test/txTest.cpp b/test/txTest.cpp index 3f67c0a2f..e2a16e16c 100644 --- a/test/txTest.cpp +++ b/test/txTest.cpp @@ -20,8 +20,6 @@ * Simple peer transaction send test. */ -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include diff --git a/test/vm.cpp b/test/vm.cpp index 00ba82aaf..e78753e6a 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -22,8 +22,6 @@ #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include diff --git a/test/vm.h b/test/vm.h index 03b3b4e5e..f27bce50b 100644 --- a/test/vm.h +++ b/test/vm.h @@ -26,8 +26,6 @@ along with cpp-ethereum. If not, see . #include #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include diff --git a/test/whisperTopic.cpp b/test/whisperTopic.cpp index 0937ab922..0ea681b67 100644 --- a/test/whisperTopic.cpp +++ b/test/whisperTopic.cpp @@ -20,8 +20,6 @@ */ #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include @@ -44,10 +42,10 @@ BOOST_AUTO_TEST_CASE(topic) Host host1("Test", NetworkPreferences(30303, "127.0.0.1", false, true)); auto whost1 = host1.registerCapability(new WhisperHost()); host1.start(); - + while (!host1.isStarted()) this_thread::sleep_for(chrono::milliseconds(2)); - + bool started = false; unsigned result = 0; std::thread listener([&]() @@ -75,19 +73,19 @@ BOOST_AUTO_TEST_CASE(topic) } this_thread::sleep_for(chrono::milliseconds(50)); } - + }); - + Host host2("Test", NetworkPreferences(30300, "127.0.0.1", false, true)); auto whost2 = host2.registerCapability(new WhisperHost()); host2.start(); - + while (!host2.isStarted()) this_thread::sleep_for(chrono::milliseconds(2)); - + this_thread::sleep_for(chrono::milliseconds(100)); host2.addNode(host1.id(), "127.0.0.1", 30303, 30303); - + this_thread::sleep_for(chrono::milliseconds(500)); while (!started) @@ -111,7 +109,7 @@ BOOST_AUTO_TEST_CASE(forwarding) cnote << "Testing Whisper forwarding..."; auto oldLogVerbosity = g_logVerbosity; g_logVerbosity = 0; - + // Host must be configured not to share peers. Host host1("Listner", NetworkPreferences(30303, "", false, true)); host1.setIdealPeerCount(0); @@ -119,7 +117,7 @@ BOOST_AUTO_TEST_CASE(forwarding) host1.start(); while (!host1.isStarted()) this_thread::sleep_for(chrono::milliseconds(2)); - + unsigned result = 0; bool done = false; @@ -146,7 +144,7 @@ BOOST_AUTO_TEST_CASE(forwarding) } }); - + // Host must be configured not to share peers. Host host2("Forwarder", NetworkPreferences(30305, "", false, true)); host2.setIdealPeerCount(1); @@ -154,7 +152,7 @@ BOOST_AUTO_TEST_CASE(forwarding) host2.start(); while (!host2.isStarted()) this_thread::sleep_for(chrono::milliseconds(2)); - + Public fwderid; bool startedForwarder = false; std::thread forwarder([&]() @@ -214,7 +212,7 @@ BOOST_AUTO_TEST_CASE(asyncforwarding) unsigned result = 0; bool done = false; - + // Host must be configured not to share peers. Host host1("Forwarder", NetworkPreferences(30305, "", false, true)); host1.setIdealPeerCount(1); @@ -227,7 +225,7 @@ BOOST_AUTO_TEST_CASE(asyncforwarding) std::thread forwarder([&]() { setThreadName("forwarder"); - + this_thread::sleep_for(chrono::milliseconds(500)); // ph.addNode("127.0.0.1", 30303, 30303); @@ -249,7 +247,7 @@ BOOST_AUTO_TEST_CASE(asyncforwarding) while (!startedForwarder) this_thread::sleep_for(chrono::milliseconds(2)); - + { Host host2("Sender", NetworkPreferences(30300, "", false, true)); host2.setIdealPeerCount(1); @@ -261,7 +259,7 @@ BOOST_AUTO_TEST_CASE(asyncforwarding) while (!host2.peerCount()) this_thread::sleep_for(chrono::milliseconds(5)); - + KeyPair us = KeyPair::create(); whost2->post(us.sec(), RLPStream().append(1).out(), BuildTopic("test")); this_thread::sleep_for(chrono::milliseconds(250)); diff --git a/third/MainWin.cpp b/third/MainWin.cpp index c91c416d8..210fabe47 100644 --- a/third/MainWin.cpp +++ b/third/MainWin.cpp @@ -21,8 +21,6 @@ #include -// Make sure boost/asio.hpp is included before windows.h. -#include #include #include