From 0ff44bd15c3fb00d93b01f811abf69964f2ec89a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 14 Aug 2015 14:20:59 +0200 Subject: [PATCH] Async transact gas determination. --- alethzero/Transact.cpp | 73 +++++++++++++++++++++--------------------- alethzero/Transact.h | 3 +- alethzero/Transact.ui | 48 ++++++++++++++++++--------- 3 files changed, 71 insertions(+), 53 deletions(-) diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index f4b331d22..ba767a6e7 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -106,7 +106,12 @@ bool Transact::isCreation() const u256 Transact::fee() const { - return ui->gas->value() * gasPrice(); + return gas() * gasPrice(); +} + +u256 Transact::gas() const +{ + return ui->gas->value() == -1 ? m_upperBound : ui->gas->value(); } u256 Transact::value() const @@ -199,10 +204,10 @@ void Transact::on_copyUnsigned_clicked() if (isCreation()) // If execution is a contract creation, add Natspec to // a local Natspec LEVELDB - t = Transaction(value(), gasPrice(), ui->gas->value(), m_data, nonce); + t = Transaction(value(), gasPrice(), gas(), m_data, nonce); else // TODO: cache like m_data. - t = Transaction(value(), gasPrice(), ui->gas->value(), toAccount().first, m_data, nonce); + t = Transaction(value(), gasPrice(), gas(), toAccount().first, m_data, nonce); qApp->clipboard()->setText(QString::fromStdString(toHex(t.rlp()))); } @@ -350,11 +355,11 @@ void Transact::timerEvent(QTimerEvent*) else er = ethereum()->call(from, value(), to, m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient); if (er.excepted == TransactionException::OutOfGas || er.excepted == TransactionException::OutOfGasBase || er.excepted == TransactionException::OutOfGasIntrinsic || er.codeDeposit == CodeDeposit::Failed) - m_lowerBound = mid; + m_lowerBound = m_lowerBound == mid ? m_upperBound : mid; else { m_lastGood = er; - m_upperBound = mid; + m_upperBound = m_upperBound == mid ? m_lowerBound : mid; } updateBounds(); @@ -371,58 +376,52 @@ void Transact::updateBounds() double nran = m_upperBound - m_lowerBound; int x = int(log2(oran / nran) * 100.0 / log2(oran * 2)); ui->progressGas->setValue(x); + ui->progressGas->setVisible(true); + ui->gas->setSpecialValueText(QString("Auto (%1 gas)").arg(m_upperBound)); } void Transact::finaliseBounds() { - qint64 baseGas = (qint64)Transaction::gasRequired(m_data, 0); - GasRequirements gasReq = GasRequirements{m_upperBound, baseGas, m_upperBound - baseGas, (qint64)m_lastGood.gasRefunded, m_lastGood}; + quint64 baseGas = (quint64)Transaction::gasRequired(m_data, 0); + ui->progressGas->setVisible(false); - QString htmlInfo = QString("
INFO Gas required: %1 total = %2 base, %3 exec [%4 refunded later]
").arg(gasReq.neededGas).arg(gasReq.baseGas).arg(gasReq.executionGas).arg(gasReq.refundedGas); + quint64 executionGas = m_upperBound - baseGas; + QString htmlInfo = QString("
INFO Gas required: %1 total = %2 base, %3 exec [%4 refunded later]
").arg(m_upperBound).arg(baseGas).arg(executionGas).arg((qint64)m_lastGood.gasRefunded); auto bail = [&](QString he) { - m_allGood = false; -// ui->send->setEnabled(false); - ui->code->setHtml(he + htmlInfo + ui->code->toHtml()); + ui->send->setEnabled(false); + ui->code->setHtml(he + htmlInfo + m_dataInfo); }; auto s = fromAccount(); auto b = ethereum()->balanceAt(s, PendingBlock); - if (b < value() + gasReq.baseGas * gasPrice()) + if (b < value() + baseGas * gasPrice()) { // Not enough - bail. bail("
ERROR Account doesn't contain enough for paying even the basic amount of gas required.
"); return; } - if (gasReq.neededGas > m_ethereum->gasLimitRemaining()) + if (m_upperBound > m_ethereum->gasLimitRemaining()) { // Not enough - bail. bail("
ERROR Gas remaining in block isn't enough to allow the gas required.
"); return; } - if (gasReq.er.excepted != TransactionException::None) + if (m_lastGood.excepted != TransactionException::None) { - bail("
ERROR " + QString::fromStdString(toString(gasReq.er.excepted)) + "
"); + bail("
ERROR " + QString::fromStdString(toString(m_lastGood.excepted)) + "
"); return; } - if (gasReq.er.codeDeposit == CodeDeposit::Failed) + if (m_lastGood.codeDeposit == CodeDeposit::Failed) { - bail("
ERROR Code deposit failed due to insufficient gas; " + QString::fromStdString(toString(gasReq.er.gasForDeposit)) + " GAS < " + QString::fromStdString(toString(gasReq.er.depositSize)) + " bytes * " + QString::fromStdString(toString(c_createDataGas)) + "GAS/byte
"); + bail("
ERROR Code deposit failed due to insufficient gas; " + QString::fromStdString(toString(m_lastGood.gasForDeposit)) + " GAS < " + QString::fromStdString(toString(m_lastGood.depositSize)) + " bytes * " + QString::fromStdString(toString(c_createDataGas)) + "GAS/byte
"); return; } - // Update gas - if (ui->gas->value() == ui->gas->minimum()) - { - ui->gas->setMinimum(gasReq.neededGas); - ui->gas->setValue(gasReq.neededGas); - } - else - ui->gas->setMinimum(gasReq.neededGas); - updateFee(); - ui->code->setHtml(htmlInfo + ui->code->toHtml()); + ui->code->setHtml(htmlInfo + m_dataInfo); + ui->send->setEnabled(true); killTimer(m_gasCalcTimer); } @@ -473,13 +472,12 @@ void Transact::rejigData() if (!s) return; - m_allGood = true; QString htmlInfo; auto bail = [&](QString he) { - m_allGood = false; -// ui->send->setEnabled(false); - ui->code->setHtml(he + htmlInfo); + ui->send->setEnabled(false); + m_dataInfo = he + htmlInfo; + ui->code->setHtml(m_dataInfo); }; // Determine m_info. @@ -513,8 +511,9 @@ void Transact::rejigData() determineGasRequirements(); - ui->code->setHtml(htmlInfo); -// ui->send->setEnabled(m_allGood); + m_dataInfo = htmlInfo; + ui->code->setHtml(m_dataInfo); + ui->send->setEnabled(true); } Secret Transact::findSecret(u256 _totalReq) const @@ -576,7 +575,7 @@ void Transact::on_send_clicked() { // If execution is a contract creation, add Natspec to // a local Natspec LEVELDB - ethereum()->submitTransaction(s, value(), m_data, ui->gas->value(), gasPrice(), nonce); + ethereum()->submitTransaction(s, value(), m_data, gas(), gasPrice(), nonce); #if ETH_SOLIDITY string src = ui->data->toPlainText().toStdString(); if (sourceIsSolidity(src)) @@ -595,7 +594,7 @@ void Transact::on_send_clicked() } else // TODO: cache like m_data. - ethereum()->submitTransaction(s, value(), toAccount().first, m_data, ui->gas->value(), gasPrice(), nonce); + ethereum()->submitTransaction(s, value(), toAccount().first, m_data, gas(), gasPrice(), nonce); close(); } @@ -614,8 +613,8 @@ void Transact::on_debug_clicked() { Block postState(ethereum()->postState()); Transaction t = isCreation() ? - Transaction(value(), gasPrice(), ui->gas->value(), m_data, postState.transactionsFrom(from)) : - Transaction(value(), gasPrice(), ui->gas->value(), toAccount().first, m_data, postState.transactionsFrom(from)); + Transaction(value(), gasPrice(), gas(), m_data, postState.transactionsFrom(from)) : + Transaction(value(), gasPrice(), gas(), toAccount().first, m_data, postState.transactionsFrom(from)); t.forceSender(from); Debugger dw(m_main, this); Executive e(postState, ethereum()->blockChain(), 0); diff --git a/alethzero/Transact.h b/alethzero/Transact.h index 4056144c2..723ff07db 100644 --- a/alethzero/Transact.h +++ b/alethzero/Transact.h @@ -88,6 +88,7 @@ private: void updateFee(); bool isCreation() const; dev::u256 fee() const; + dev::u256 gas() const; dev::u256 total() const; dev::u256 value() const; dev::u256 gasPrice() const; @@ -108,8 +109,8 @@ private: dev::eth::Client* m_ethereum = nullptr; MainFace* m_main = nullptr; NatSpecFace* m_natSpecDB = nullptr; - bool m_allGood = false; + QString m_dataInfo; qint64 m_startLowerBound = 0; qint64 m_startUpperBound = 0; qint64 m_lowerBound = 0; diff --git a/alethzero/Transact.ui b/alethzero/Transact.ui index 3c78e3db7..94b329842 100644 --- a/alethzero/Transact.ui +++ b/alethzero/Transact.ui @@ -6,7 +6,7 @@ 0 0 - 543 + 604 695 @@ -23,17 +23,20 @@ + + Automatic + gas - 1 + -1 430000000 - 10000 + -1 @@ -261,7 +264,20 @@ - + + + + gas + + + max + + + 450000000 + + + + true @@ -272,10 +288,22 @@ min + + 0 + + + 450000000 + - + + + + 0 + 0 + + 24 @@ -284,16 +312,6 @@ - - - - gas - - - max - - -