From c7167d183b5b345566005624909c0d1c293fdca9 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 7 Apr 2015 18:09:29 +0200 Subject: [PATCH 1/3] auto gas calculation --- mix/ClientModel.cpp | 31 +++++++++---- mix/ClientModel.h | 21 ++++++--- mix/MachineStates.h | 1 + mix/MixApplication.cpp | 7 +-- mix/MixClient.cpp | 80 ++++++++++++++++++++++++++------- mix/MixClient.h | 7 ++- mix/qml/DeploymentDialog.qml | 8 +++- mix/qml/StateListModel.qml | 2 + mix/qml/TransactionDialog.qml | 11 +++++ mix/qml/TransactionLog.qml | 5 +++ mix/qml/js/TransactionHelper.js | 1 + 11 files changed, 138 insertions(+), 36 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 731a5cb7e..7617ac630 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -154,6 +154,14 @@ QVariantMap ClientModel::contractAddresses() const return res; } +QVariantMap ClientModel::gasCosts() const +{ + QVariantMap res; + for (auto const& c: m_gasCosts) + res.insert(c.first, QVariant::fromValue(static_cast(c.second))); + return res; +} + void ClientModel::setupState(QVariantMap _state) { QVariantList balances = _state.value("accounts").toList(); @@ -173,6 +181,7 @@ void ClientModel::setupState(QVariantMap _state) QString contractId = transaction.value("contractId").toString(); QString functionId = transaction.value("functionId").toString(); u256 gas = boost::get(qvariant_cast(transaction.value("gas"))->internalValue()); + bool gasAuto = transaction.value("gas").toBool(); u256 value = (qvariant_cast(transaction.value("value")))->toU256Wei(); u256 gasPrice = (qvariant_cast(transaction.value("gasPrice")))->toU256Wei(); QString sender = transaction.value("sender").toString(); @@ -183,7 +192,7 @@ void ClientModel::setupState(QVariantMap _state) contractId = functionId; TransactionSettings transactionSettings(contractId, transaction.value("url").toString()); transactionSettings.gasPrice = 10000000000000; - transactionSettings.gas = 125000; + transactionSettings.gasAuto = true; transactionSettings.value = 0; transactionSettings.sender = Secret(sender.toStdString()); transactionSequence.push_back(transactionSettings); @@ -192,7 +201,7 @@ void ClientModel::setupState(QVariantMap _state) { if (contractId.isEmpty() && m_codeModel->hasContract()) //TODO: This is to support old project files, remove later contractId = m_codeModel->contracts().keys()[0]; - TransactionSettings transactionSettings(contractId, functionId, value, gas, gasPrice, Secret(sender.toStdString())); + TransactionSettings transactionSettings(contractId, functionId, value, gas, gasAuto, gasPrice, Secret(sender.toStdString())); transactionSettings.parameterValues = transaction.value("parameters").toMap(); if (contractId == functionId || functionId == "Constructor") @@ -228,7 +237,7 @@ void ClientModel::executeSequence(vector const& _sequence, //std contract bytes const& stdContractCode = m_codeModel->getStdContractCode(transaction.contractId, transaction.stdContractUrl); TransactionSettings stdTransaction = transaction; - stdTransaction.gas = 500000;// TODO: get this from std contracts library + stdTransaction.gasAuto = true; Address address = deployContract(stdContractCode, stdTransaction); m_stdContractAddresses[stdTransaction.contractId] = address; m_stdContractNames[address] = stdTransaction.contractId; @@ -277,6 +286,8 @@ void ClientModel::executeSequence(vector const& _sequence, m_contractNames[newAddress] = transaction.contractId; contractAddressesChanged(); } + gasCostsChanged(); + m_gasCosts[transaction.contractId] = m_client->lastExecution().gasUsed; } else { @@ -507,13 +518,13 @@ void ClientModel::debugRecord(unsigned _index) Address ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction) { - Address newAddress = m_client->submitTransaction(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice); + Address newAddress = m_client->submitTransaction(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice, _ctrTransaction.gasAuto); return newAddress; } void ClientModel::callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr) { - m_client->submitTransaction(_tr.sender, _tr.value, _contract, _data, _tr.gas, _tr.gasPrice); + m_client->submitTransaction(_tr.sender, _tr.value, _contract, _data, _tr.gas, _tr.gasPrice, _tr.gasAuto); } RecordLogEntry* ClientModel::lastBlock() const @@ -523,7 +534,7 @@ RecordLogEntry* ClientModel::lastBlock() const strGas << blockInfo.gasUsed; stringstream strNumber; strNumber << blockInfo.number; - RecordLogEntry* record = new RecordLogEntry(0, QString::fromStdString(strNumber.str()), tr(" - Block - "), tr("Hash: ") + QString(QString::fromStdString(toHex(blockInfo.hash().ref()))), tr("Gas Used: ") + QString::fromStdString(strGas.str()), QString(), QString(), false, RecordLogEntry::RecordType::Block); + RecordLogEntry* record = new RecordLogEntry(0, QString::fromStdString(strNumber.str()), tr(" - Block - "), tr("Hash: ") + QString(QString::fromStdString(toHex(blockInfo.hash().ref()))), QString(), QString(), QString(), false, RecordLogEntry::RecordType::Block, QString::fromStdString(strGas.str())); QQmlEngine::setObjectOwnership(record, QQmlEngine::JavaScriptOwnership); return record; } @@ -544,13 +555,17 @@ void ClientModel::onNewTransaction() unsigned recordIndex = tr.executonIndex; QString transactionIndex = tr.isCall() ? QObject::tr("Call") : QString("%1:%2").arg(block).arg(tr.transactionIndex); QString address = QString::fromStdString(toJS(tr.address)); - QString value = QString::fromStdString(toString(tr.value)); + QString value = QString::fromStdString(toString(tr.value)); QString contract = address; QString function; QString returned; + QString gasUsed; bool creation = (bool)tr.contractAddress; + if (!tr.isCall()) + gasUsed = QString::fromStdString(toString(tr.gasUsed)); + //TODO: handle value transfer FixedHash<4> functionHash; bool abi = false; @@ -605,7 +620,7 @@ void ClientModel::onNewTransaction() } } - RecordLogEntry* log = new RecordLogEntry(recordIndex, transactionIndex, contract, function, value, address, returned, tr.isCall(), RecordLogEntry::RecordType::Transaction); + RecordLogEntry* log = new RecordLogEntry(recordIndex, transactionIndex, contract, function, value, address, returned, tr.isCall(), RecordLogEntry::RecordType::Transaction, gasUsed); QQmlEngine::setObjectOwnership(log, QQmlEngine::JavaScriptOwnership); emit newRecord(log); } diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 4b597a1ea..ddc0e6cf1 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -48,10 +48,10 @@ struct SolidityType; struct TransactionSettings { TransactionSettings() {} - 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& _contractId, QString const& _functionId, u256 _value, u256 _gas, bool _gasAuto, u256 _gasPrice, Secret _sender): + contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasAuto(_gasAuto), gasPrice(_gasPrice), sender(_sender) {} TransactionSettings(QString const& _stdContractName, QString const& _stdContractUrl): - contractId(_stdContractName), stdContractUrl(_stdContractUrl) {} + contractId(_stdContractName), gasAuto(true), stdContractUrl(_stdContractUrl) {} /// Contract name QString contractId; @@ -61,6 +61,8 @@ struct TransactionSettings u256 value; /// Gas u256 gas; + /// Calculate gas automatically + bool gasAuto = true; /// Gas price u256 gasPrice; /// Mapping from contract function parameter name to value @@ -95,6 +97,8 @@ class RecordLogEntry: public QObject Q_PROPERTY(bool call MEMBER m_call CONSTANT) /// @returns record type Q_PROPERTY(RecordType type MEMBER m_type CONSTANT) + /// Gas used + Q_PROPERTY(QString gasUsed MEMBER m_gasUsed CONSTANT) public: enum RecordType @@ -105,8 +109,8 @@ public: RecordLogEntry(): m_recordIndex(0), m_call(false), m_type(RecordType::Transaction) {} - RecordLogEntry(unsigned _recordIndex, QString _transactionIndex, QString _contract, QString _function, QString _value, QString _address, QString _returned, bool _call, RecordType _type): - m_recordIndex(_recordIndex), m_transactionIndex(_transactionIndex), m_contract(_contract), m_function(_function), m_value(_value), m_address(_address), m_returned(_returned), m_call(_call), m_type(_type) {} + RecordLogEntry(unsigned _recordIndex, QString _transactionIndex, QString _contract, QString _function, QString _value, QString _address, QString _returned, bool _call, RecordType _type, QString _gasUsed): + m_recordIndex(_recordIndex), m_transactionIndex(_transactionIndex), m_contract(_contract), m_function(_function), m_value(_value), m_address(_address), m_returned(_returned), m_call(_call), m_type(_type), m_gasUsed(_gasUsed) {} private: unsigned m_recordIndex; @@ -118,6 +122,7 @@ private: QString m_returned; bool m_call; RecordType m_type; + QString m_gasUsed; }; /** @@ -136,6 +141,8 @@ public: Q_PROPERTY(bool mining MEMBER m_mining NOTIFY miningStateChanged) /// @returns deployed contracts addresses Q_PROPERTY(QVariantMap contractAddresses READ contractAddresses NOTIFY contractAddressesChanged) + /// @returns deployed contracts gas costs + Q_PROPERTY(QVariantMap gasCosts READ gasCosts NOTIFY gasCostsChanged) // @returns the last block Q_PROPERTY(RecordLogEntry* lastBlock READ lastBlock CONSTANT) /// ethereum.js RPC request entry point @@ -180,6 +187,8 @@ signals: void runFailed(QString const& _message); /// Contract address changed void contractAddressesChanged(); + /// Gas costs updated + void gasCostsChanged(); /// Execution state changed void newBlock(); /// Execution state changed @@ -197,6 +206,7 @@ signals: private: RecordLogEntry* lastBlock() const; QVariantMap contractAddresses() const; + QVariantMap gasCosts() const; 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); @@ -212,6 +222,7 @@ private: std::unique_ptr m_client; std::unique_ptr m_rpcConnector; std::unique_ptr m_web3Server; + std::map m_gasCosts; std::map m_contractAddresses; std::map m_contractNames; std::map m_stdContractAddresses; diff --git a/mix/MachineStates.h b/mix/MachineStates.h index f0346ba1e..afd2b990a 100644 --- a/mix/MachineStates.h +++ b/mix/MachineStates.h @@ -80,6 +80,7 @@ namespace mix dev::Address sender; dev::Address contractAddress; dev::u256 value; + dev::u256 gasUsed; unsigned transactionIndex; unsigned executonIndex = 0; diff --git a/mix/MixApplication.cpp b/mix/MixApplication.cpp index 54c860a8d..4822b8da5 100644 --- a/mix/MixApplication.cpp +++ b/mix/MixApplication.cpp @@ -52,13 +52,8 @@ ApplicationService::ApplicationService() MixApplication::MixApplication(int& _argc, char* _argv[]): QApplication(_argc, _argv), m_engine(new QQmlApplicationEngine()) { + setWindowIcon(QIcon(":/res/mix_256x256x32.png")); m_engine->load(QUrl("qrc:/qml/Application.qml")); - if (!m_engine->rootObjects().empty()) - { - QWindow *window = qobject_cast(m_engine->rootObjects().at(0)); - if (window) - window->setIcon(QIcon(":/res/mix_256x256x32.png")); - } } void MixApplication::initialize() diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 58cab151d..60d97e5b7 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -40,10 +40,8 @@ namespace dev namespace mix { -// TODO: merge as much as possible with the Client.cpp into a mutually inherited base class. - -const Secret c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); -const u256 c_mixGenesisDifficulty = c_minimumDifficulty; //TODO: make it lower for Mix somehow +Secret const c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); +u256 const c_mixGenesisDifficulty = c_minimumDifficulty; //TODO: make it lower for Mix somehow bytes MixBlockChain::createGenesisBlock(h256 _stateRoot) { @@ -100,9 +98,18 @@ void MixClient::resetState(std::map _accounts) m_executions.clear(); } -void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _call) +Transaction MixClient::replaceGas(Transaction const& _t, Secret const& _secret, u256 const& _gas) +{ + if (_t.isCreation()) + return Transaction(_t.value(), _t.gasPrice(), _gas, _t.data(), _t.nonce(), _secret); + else + return Transaction(_t.value(), _t.gasPrice(), _gas, _t.receiveAddress(), _t.data(), _t.nonce(), _secret); +} + +void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _call, bool _gasAuto, Secret const& _secret) { - bytes rlp = _t.rlp(); + Transaction t = _gasAuto ? replaceGas(_t, _secret, m_state.gasLimitRemaining()) : _t; + bytes rlp = t.rlp(); // do debugging run first LastHashes lastHashes(256); @@ -167,6 +174,31 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c execution.go(onOp); execution.finalize(); + dev::eth::ExecutionResult er = execution.executionResult(); + + switch (er.excepted) + { + case TransactionException::None: + break; + case TransactionException::NotEnoughCash: + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Insufficient balance for contract deployment")); + case TransactionException::OutOfGasBase: + case TransactionException::OutOfGas: + BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Not enough gas")); + case TransactionException::BlockGasLimitReached: + BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Block gas limit reached")); + case TransactionException::OutOfStack: + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Out of stack")); + case TransactionException::StackUnderflow: + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Stack underflow")); + //these should not happen in mix + case TransactionException::Unknown: + case TransactionException::BadInstruction: + case TransactionException::BadJumpDestination: + case TransactionException::InvalidSignature: + case TransactionException::InvalidNonce: + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Internal execution error")); + }; ExecutionResult d; d.result = execution.executionResult(); @@ -176,6 +208,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c d.address = _t.receiveAddress(); d.sender = _t.sender(); d.value = _t.value(); + d.gasUsed = er.gasUsed + er.gasRefunded; if (_t.isCreation()) d.contractAddress = right160(sha3(rlpList(_t.sender(), _t.nonce()))); if (!_call) @@ -185,9 +218,11 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c // execute on a state if (!_call) { - dev::eth::ExecutionResult er =_state.execute(lastHashes, _t); - if (_t.isCreation() && _state.code(d.contractAddress).empty()) + t = _gasAuto ? replaceGas(_t, _secret, d.gasUsed) : _t; + er =_state.execute(lastHashes, t); + if (t.isCreation() && _state.code(d.contractAddress).empty()) BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Not enough gas for contract deployment")); + d.gasUsed = er.gasUsed + er.gasRefunded + er.gasForDeposit; // collect watches h256Set changed; Guard l(x_filtersWatches); @@ -242,25 +277,25 @@ State MixClient::asOf(h256 const& _block) const return State(m_stateDB, bc(), _block); } -void MixClient::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) +void MixClient::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, bool _gasAuto) { WriteGuard l(x_state); u256 n = m_state.transactionsFrom(toAddress(_secret)); Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); - executeTransaction(t, m_state, false); + executeTransaction(t, m_state, false, _gasAuto, _secret); } -Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) +Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice, bool _gasAuto) { WriteGuard l(x_state); u256 n = m_state.transactionsFrom(toAddress(_secret)); eth::Transaction t(_endowment, _gasPrice, _gas, _init, n, _secret); - executeTransaction(t, m_state, false); + executeTransaction(t, m_state, false, _gasAuto, _secret); Address address = right160(sha3(rlpList(t.sender(), t.nonce()))); return address; } -dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) +dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto) { (void)_blockNumber; State temp = asOf(eth::PendingBlock); @@ -268,10 +303,25 @@ dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _ Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); bytes rlp = t.rlp(); WriteGuard lw(x_state); //TODO: lock is required only for last execution state - executeTransaction(t, temp, true); + executeTransaction(t, temp, true, _gasAuto, _secret); return lastExecution().result; } +void MixClient::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) +{ + submitTransaction(_secret, _value, _dest, _data, _gas, _gasPrice, false); +} + +Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) +{ + return submitTransaction(_secret, _endowment, _init, _gas, _gasPrice, false); +} + +dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) +{ + return call(_secret, _value, _dest, _data, _gas, _gasPrice, _blockNumber,false); +} + dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) { (void)_blockNumber; @@ -285,7 +335,7 @@ dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes c Transaction t(_value, _gasPrice, _gas, _data, n, _secret); bytes rlp = t.rlp(); WriteGuard lw(x_state); //TODO: lock is required only for last execution state - executeTransaction(t, temp, true); + executeTransaction(t, temp, true, false, _secret); return lastExecution().result; } diff --git a/mix/MixClient.h b/mix/MixClient.h index abd9445c7..c52e7bd88 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -58,6 +58,10 @@ public: dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber = eth::PendingBlock) override; dev::eth::ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * eth::szabo, eth::BlockNumber _blockNumber = eth::PendingBlock) override; + void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, bool _gasAuto); + Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice, bool _gasAuto); + dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber, bool _gasAuto); + void setAddress(Address _us) override; void setMiningThreads(unsigned _threads) override; unsigned miningThreads() const override; @@ -86,8 +90,9 @@ protected: virtual void prepareForTransaction() override {} private: - void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state, bool _call); + void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state, bool _call, bool _gasAuto, dev::Secret const& _secret); void noteChanged(h256Set const& _filters); + dev::eth::Transaction replaceGas(dev::eth::Transaction const& _t, dev::Secret const& _secret, dev::u256 const& _gas); std::vector m_userAccounts; eth::State m_state; diff --git a/mix/qml/DeploymentDialog.qml b/mix/qml/DeploymentDialog.qml index 2e7e1601b..aa8d67836 100644 --- a/mix/qml/DeploymentDialog.qml +++ b/mix/qml/DeploymentDialog.qml @@ -73,6 +73,12 @@ Dialog { balance.text = comboAccounts.balances[0]; }); }); + + var gas = 0; + var gasCosts = clientModel.gasCosts; + for (var g in gasCosts) + gas += gasCosts[g]; + gasToUse = gas; } function stopForInputError(inError) @@ -373,7 +379,7 @@ Dialog { Layout.preferredWidth: 350 id: localPackageUrl readOnly: true - enabled: rowRegister.isOkToRegister() + } DefaultLabel diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index c90692572..7b7f33361 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -44,6 +44,7 @@ Item { value: QEtherHelper.createEther(t.value.value, t.value.unit), gas: QEtherHelper.createBigInt(t.gas.value), gasPrice: QEtherHelper.createEther(t.gasPrice.value, t.gasPrice.unit), + gasAuto: t.gasAuto, stdContract: t.stdContract ? true : false, parameters: {}, sender: t.sender @@ -91,6 +92,7 @@ Item { url: t.url, value: { value: t.value.value, unit: t.value.unit }, gas: { value: t.gas.value() }, + gasAuto: t.gasAuto, gasPrice: { value: t.gasPrice.value, unit: t.gasPrice.unit }, stdContract: t.stdContract, parameters: {} diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index f53e16a06..2c36bf2ea 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -17,6 +17,7 @@ Dialog { title: qsTr("Edit Transaction") property int transactionIndex property alias gas: gasValueEdit.gasValue; + property alias gasAuto: gasAutoCheck.checked; property alias gasPrice: gasPriceField.value; property alias transactionValue: valueField.value; property string contractId: contractComboBox.currentValue(); @@ -39,6 +40,7 @@ Dialog { transactionIndex = index; gasValueEdit.gasValue = item.gas; + gasAutoCheck.checked = item.gasAuto ? true : false; gasPriceField.value = item.gasPrice; valueField.value = item.value; var contractId = item.contractId; @@ -164,6 +166,7 @@ Dialog { contractId: transactionDialog.contractId, functionId: transactionDialog.functionId, gas: transactionDialog.gas, + gasAuto: transactionDialog.gasAuto, gasPrice: transactionDialog.gasPrice, value: transactionDialog.transactionValue, parameters: {}, @@ -314,8 +317,16 @@ Dialog { onGasValueChanged: text = gasValue.value(); onTextChanged: gasValue.setValue(text); implicitWidth: 200 + enabled: !gasAutoCheck.checked id: gasValueEdit; } + + CheckBox + { + id: gasAutoCheck + checked: true + text: qsTr("Auto"); + } } CommonSeparator diff --git a/mix/qml/TransactionLog.qml b/mix/qml/TransactionLog.qml index 5668c6e05..ad97846ae 100644 --- a/mix/qml/TransactionLog.qml +++ b/mix/qml/TransactionLog.qml @@ -127,6 +127,11 @@ Item { title: qsTr("Returned") width: 120 } + TableViewColumn { + role: "gasUsed" + title: qsTr("Gas Used") + width: 120 + } onActivated: { var item = logTable.model.get(row); if (item.type === RecordLogEntry.Transaction) diff --git a/mix/qml/js/TransactionHelper.js b/mix/qml/js/TransactionHelper.js index 5668030be..7393878fe 100644 --- a/mix/qml/js/TransactionHelper.js +++ b/mix/qml/js/TransactionHelper.js @@ -6,6 +6,7 @@ function defaultTransaction() value: createEther("0", QEther.Wei), functionId: "", gas: createBigInt("250000"), + gasAuto: true, gasPrice: createEther("100000", QEther.Wei), parameters: {}, stdContract: false From a3455862e4791cb7acae9f92458e736d5199d6d2 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 7 Apr 2015 18:23:17 +0200 Subject: [PATCH 2/3] removed obsolete line --- mix/test/TestService.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/mix/test/TestService.cpp b/mix/test/TestService.cpp index 751c2379a..75f69a9eb 100644 --- a/mix/test/TestService.cpp +++ b/mix/test/TestService.cpp @@ -163,7 +163,6 @@ bool TestService::keyClickChar(QObject* _item, QString const& _character, int _m bool TestService::mouseClick(QObject* _item, qreal _x, qreal _y, int _button, int _modifiers, int _delay) { QWindow* window = qobject_cast(_item); - QMetaObject const* mo = _item->metaObject(); if (!window) window = eventWindow(_item); mouseEvent(MouseClick, window, _item, Qt::MouseButton(_button), Qt::KeyboardModifiers(_modifiers), QPointF(_x, _y), _delay); From 5e319fa29ba9d8b2fcd49026fc275c547e12a5c7 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 8 Apr 2015 10:34:02 +0200 Subject: [PATCH 3/3] fixed autogas setting --- mix/ClientModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 7617ac630..41aa55249 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -181,7 +181,7 @@ void ClientModel::setupState(QVariantMap _state) QString contractId = transaction.value("contractId").toString(); QString functionId = transaction.value("functionId").toString(); u256 gas = boost::get(qvariant_cast(transaction.value("gas"))->internalValue()); - bool gasAuto = transaction.value("gas").toBool(); + bool gasAuto = transaction.value("gasAuto").toBool(); u256 value = (qvariant_cast(transaction.value("value")))->toU256Wei(); u256 gasPrice = (qvariant_cast(transaction.value("gasPrice")))->toU256Wei(); QString sender = transaction.value("sender").toString();