Browse Source

Merge pull request #2822 from ethereum/transactasyncgas

Async Transact dialog for gas determination.
cl-refactor
Gav Wood 10 years ago
parent
commit
1a5039f476
  1. 185
      alethzero/Transact.cpp
  2. 14
      alethzero/Transact.h
  3. 323
      alethzero/Transact.ui

185
alethzero/Transact.cpp

@ -104,7 +104,12 @@ bool Transact::isCreation() const
u256 Transact::fee() 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 u256 Transact::value() const
@ -197,10 +202,10 @@ void Transact::on_copyUnsigned_clicked()
if (isCreation()) if (isCreation())
// If execution is a contract creation, add Natspec to // If execution is a contract creation, add Natspec to
// a local Natspec LEVELDB // a local Natspec LEVELDB
t = Transaction(value(), gasPrice(), ui->gas->value(), m_data, nonce); t = Transaction(value(), gasPrice(), gas(), m_data, nonce);
else else
// TODO: cache like m_data. // 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()))); qApp->clipboard()->setText(QString::fromStdString(toHex(t.rlp())));
} }
@ -334,6 +339,90 @@ pair<Address, bytes> Transact::toAccount()
return p; return p;
} }
void Transact::timerEvent(QTimerEvent*)
{
Address from = fromAccount();
Address to = toAccount().first;
if (m_upperBound != m_lowerBound)
{
qint64 mid = (m_lowerBound + m_upperBound) / 2;
ExecutionResult er;
if (isCreation())
er = ethereum()->create(from, value(), m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient);
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 = m_lowerBound == mid ? m_upperBound : mid;
else
{
m_lastGood = er;
m_upperBound = m_upperBound == mid ? m_lowerBound : mid;
}
updateBounds();
if (m_lowerBound == m_upperBound)
finaliseBounds();
}
}
void Transact::updateBounds()
{
ui->minGas->setValue(m_lowerBound);
ui->maxGas->setValue(m_upperBound);
double oran = m_startUpperBound - m_startLowerBound;
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()
{
quint64 baseGas = (quint64)Transaction::gasRequired(m_data, 0);
ui->progressGas->setVisible(false);
quint64 executionGas = m_upperBound - baseGas;
QString htmlInfo = QString("<div class=\"info\"><span class=\"icon\">INFO</span> Gas required: %1 total = %2 base, %3 exec [%4 refunded later]</div>").arg(m_upperBound).arg(baseGas).arg(executionGas).arg((qint64)m_lastGood.gasRefunded);
auto bail = [&](QString he) {
ui->send->setEnabled(false);
ui->code->setHtml(he + htmlInfo + m_dataInfo);
};
auto s = fromAccount();
auto b = ethereum()->balanceAt(s, PendingBlock);
if (b < value() + baseGas * gasPrice())
{
// Not enough - bail.
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Account doesn't contain enough for paying even the basic amount of gas required.</div>");
return;
}
if (m_upperBound > m_ethereum->gasLimitRemaining())
{
// Not enough - bail.
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Gas remaining in block isn't enough to allow the gas required.</div>");
return;
}
if (m_lastGood.excepted != TransactionException::None)
{
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> " + QString::fromStdString(toString(m_lastGood.excepted)) + "</div>");
return;
}
if (m_lastGood.codeDeposit == CodeDeposit::Failed)
{
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Code deposit failed due to insufficient gas; " + QString::fromStdString(toString(m_lastGood.gasForDeposit)) + " GAS &lt; " + QString::fromStdString(toString(m_lastGood.depositSize)) + " bytes * " + QString::fromStdString(toString(c_createDataGas)) + "GAS/byte</div>");
return;
}
updateFee();
ui->code->setHtml(htmlInfo + m_dataInfo);
ui->send->setEnabled(true);
killTimer(m_gasCalcTimer);
}
GasRequirements Transact::determineGasRequirements() GasRequirements Transact::determineGasRequirements()
{ {
// Determine the minimum amount of gas we need to play... // Determine the minimum amount of gas we need to play...
@ -343,12 +432,11 @@ GasRequirements Transact::determineGasRequirements()
Address to = toAccount().first; Address to = toAccount().first;
ExecutionResult lastGood; ExecutionResult lastGood;
bool haveUpperBound = false; m_startLowerBound = baseGas;
qint64 lowerBound = baseGas; m_startUpperBound = (qint64)ethereum()->gasLimitRemaining();
qint64 upperBound = (qint64)ethereum()->gasLimitRemaining(); for (unsigned i = 0; i < 30; ++i)
for (unsigned i = 0; i < 30 && ((haveUpperBound && upperBound - lowerBound > 16) || !haveUpperBound); ++i) // get to with 100.
{ {
qint64 mid = haveUpperBound ? (lowerBound + upperBound) / 2 : upperBound; qint64 mid = m_startUpperBound;
ExecutionResult er; ExecutionResult er;
if (isCreation()) if (isCreation())
er = ethereum()->create(from, value(), m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient); er = ethereum()->create(from, value(), m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient);
@ -356,23 +444,21 @@ GasRequirements Transact::determineGasRequirements()
er = ethereum()->call(from, value(), to, m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient); 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) if (er.excepted == TransactionException::OutOfGas || er.excepted == TransactionException::OutOfGasBase || er.excepted == TransactionException::OutOfGasIntrinsic || er.codeDeposit == CodeDeposit::Failed)
{ {
lowerBound = mid; m_startLowerBound = mid;
if (!haveUpperBound) m_startUpperBound *= 2;
upperBound *= 2;
} }
else else
{ {
lastGood = er; // Begin async binary chop for gas calculation..
if (haveUpperBound) m_lastGood = lastGood;
upperBound = mid; m_lowerBound = m_startLowerBound;
else m_upperBound = m_startUpperBound;
haveUpperBound = true; killTimer(m_gasCalcTimer);
m_gasCalcTimer = startTimer(0);
return GasRequirements{m_upperBound, baseGas, m_upperBound - baseGas, (qint64)lastGood.gasRefunded, lastGood};
} }
} }
return GasRequirements();
// Dry-run execution to determine gas requirement and any execution errors
// (qint64)(er.gasUsed + er.gasRefunded + c_callStipend);
return GasRequirements{upperBound, baseGas, upperBound - baseGas, (qint64)lastGood.gasRefunded, lastGood};
} }
void Transact::rejigData() void Transact::rejigData()
@ -386,15 +472,12 @@ void Transact::rejigData()
if (!s) if (!s)
return; return;
auto b = ethereum()->balanceAt(s, PendingBlock);
m_allGood = true;
QString htmlInfo; QString htmlInfo;
auto bail = [&](QString he) { auto bail = [&](QString he) {
m_allGood = false; ui->send->setEnabled(false);
// ui->send->setEnabled(false); m_dataInfo = he + htmlInfo;
ui->code->setHtml(he + htmlInfo); ui->code->setHtml(m_dataInfo);
}; };
// Determine m_info. // Determine m_info.
@ -422,49 +505,15 @@ void Transact::rejigData()
htmlInfo += "<h4>Hex</h4>" + QString(ETH_HTML_DIV(ETH_HTML_MONO)) + QString::fromStdString(toHex(m_data)) + "</div>"; htmlInfo += "<h4>Hex</h4>" + QString(ETH_HTML_DIV(ETH_HTML_MONO)) + QString::fromStdString(toHex(m_data)) + "</div>";
auto gasReq = determineGasRequirements();
htmlInfo = QString("<div class=\"info\"><span class=\"icon\">INFO</span> Gas required: %1 total = %2 base, %3 exec [%4 refunded later]</div>").arg(gasReq.neededGas).arg(gasReq.baseGas).arg(gasReq.executionGas).arg(gasReq.refundedGas) + htmlInfo;
if (b < value() + gasReq.baseGas * gasPrice())
{
// Not enough - bail.
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Account doesn't contain enough for paying even the basic amount of gas required.</div>");
return;
}
if (gasReq.neededGas > m_ethereum->gasLimitRemaining())
{
// Not enough - bail.
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Gas remaining in block isn't enough to allow the gas required.</div>");
return;
}
if (gasReq.er.excepted != TransactionException::None)
{
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> " + QString::fromStdString(toString(gasReq.er.excepted)) + "</div>");
return;
}
if (gasReq.er.codeDeposit == CodeDeposit::Failed)
{
bail("<div class=\"error\"><span class=\"icon\">ERROR</span> Code deposit failed due to insufficient gas; " + QString::fromStdString(toString(gasReq.er.gasForDeposit)) + " GAS &lt; " + QString::fromStdString(toString(gasReq.er.depositSize)) + " bytes * " + QString::fromStdString(toString(c_createDataGas)) + "GAS/byte</div>");
return;
}
// Add Natspec information // Add Natspec information
if (!isCreation()) if (!isCreation())
htmlInfo = "<div class=\"info\"><span class=\"icon\">INFO</span> " + QString::fromStdString(natspecNotice(toAccount().first, m_data)).toHtmlEscaped() + "</div>" + htmlInfo; htmlInfo = "<div class=\"info\"><span class=\"icon\">INFO</span> " + QString::fromStdString(natspecNotice(toAccount().first, m_data)).toHtmlEscaped() + "</div>" + htmlInfo;
// Update gas determineGasRequirements();
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); m_dataInfo = htmlInfo;
// ui->send->setEnabled(m_allGood); ui->code->setHtml(m_dataInfo);
ui->send->setEnabled(true);
} }
Secret Transact::findSecret(u256 _totalReq) const Secret Transact::findSecret(u256 _totalReq) const
@ -526,7 +575,7 @@ void Transact::on_send_clicked()
{ {
// If execution is a contract creation, add Natspec to // If execution is a contract creation, add Natspec to
// a local Natspec LEVELDB // 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 #if ETH_SOLIDITY
string src = ui->data->toPlainText().toStdString(); string src = ui->data->toPlainText().toStdString();
if (sourceIsSolidity(src)) if (sourceIsSolidity(src))
@ -545,7 +594,7 @@ void Transact::on_send_clicked()
} }
else else
// TODO: cache like m_data. // 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(); close();
} }
@ -564,8 +613,8 @@ void Transact::on_debug_clicked()
{ {
Block postState(ethereum()->postState()); Block postState(ethereum()->postState());
Transaction t = isCreation() ? Transaction t = isCreation() ?
Transaction(value(), gasPrice(), ui->gas->value(), m_data, postState.transactionsFrom(from)) : Transaction(value(), gasPrice(), gas(), m_data, postState.transactionsFrom(from)) :
Transaction(value(), gasPrice(), ui->gas->value(), toAccount().first, m_data, postState.transactionsFrom(from)); Transaction(value(), gasPrice(), gas(), toAccount().first, m_data, postState.transactionsFrom(from));
t.forceSender(from); t.forceSender(from);
Debugger dw(m_main, this); Debugger dw(m_main, this);
Executive e(postState, ethereum()->blockChain(), 0); Executive e(postState, ethereum()->blockChain(), 0);

14
alethzero/Transact.h

@ -79,6 +79,8 @@ private:
dev::eth::Client* ethereum() const { return m_ethereum; } dev::eth::Client* ethereum() const { return m_ethereum; }
void rejigData(); void rejigData();
void updateNonce(); void updateNonce();
void updateBounds();
void finaliseBounds();
dev::Address fromAccount(); dev::Address fromAccount();
std::pair<dev::Address, bytes> toAccount(); std::pair<dev::Address, bytes> toAccount();
@ -86,6 +88,7 @@ private:
void updateFee(); void updateFee();
bool isCreation() const; bool isCreation() const;
dev::u256 fee() const; dev::u256 fee() const;
dev::u256 gas() const;
dev::u256 total() const; dev::u256 total() const;
dev::u256 value() const; dev::u256 value() const;
dev::u256 gasPrice() const; dev::u256 gasPrice() const;
@ -95,6 +98,8 @@ private:
std::string natspecNotice(dev::Address _to, dev::bytes const& _data); std::string natspecNotice(dev::Address _to, dev::bytes const& _data);
dev::Secret findSecret(dev::u256 _totalReq) const; dev::Secret findSecret(dev::u256 _totalReq) const;
void timerEvent(QTimerEvent*) override;
Ui::Transact* ui = nullptr; Ui::Transact* ui = nullptr;
unsigned m_backupGas = 0; unsigned m_backupGas = 0;
@ -104,9 +109,14 @@ private:
dev::eth::Client* m_ethereum = nullptr; dev::eth::Client* m_ethereum = nullptr;
MainFace* m_main = nullptr; MainFace* m_main = nullptr;
NatSpecFace* m_natSpecDB = nullptr; NatSpecFace* m_natSpecDB = nullptr;
bool m_allGood = false;
bool m_determiningGas = false; QString m_dataInfo;
qint64 m_startLowerBound = 0;
qint64 m_startUpperBound = 0;
qint64 m_lowerBound = 0;
qint64 m_upperBound = 0;
eth::ExecutionResult m_lastGood;
int m_gasCalcTimer = 0;
}; };
} }

323
alethzero/Transact.ui

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>543</width> <width>604</width>
<height>695</height> <height>695</height>
</rect> </rect>
</property> </property>
@ -14,87 +14,175 @@
<string>Transact</string> <string>Transact</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="10" column="2">
<widget class="QPushButton" name="debug">
<property name="text">
<string>&amp;Debug</string>
</property>
</widget>
</item>
<item row="4" column="1"> <item row="4" column="1">
<widget class="QSpinBox" name="gas"> <widget class="QSpinBox" name="gas">
<property name="specialValueText">
<string>Automatic</string>
</property>
<property name="suffix"> <property name="suffix">
<string> gas</string> <string> gas</string>
</property> </property>
<property name="minimum"> <property name="minimum">
<number>1</number> <number>-1</number>
</property> </property>
<property name="maximum"> <property name="maximum">
<number>430000000</number> <number>430000000</number>
</property> </property>
<property name="value"> <property name="value">
<number>10000</number> <number>-1</number>
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="0"> <item row="3" column="3">
<widget class="QPushButton" name="cancel"> <widget class="QComboBox" name="valueUnits"/>
</item>
<item row="4" column="3">
<widget class="QComboBox" name="gasPriceUnits"/>
</item>
<item row="2" column="1" colspan="3">
<widget class="QLineEdit" name="calculatedName">
<property name="enabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string/>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QCheckBox" name="optimize">
<property name="text"> <property name="text">
<string>&amp;Cancel</string> <string>&amp;Optimise</string>
</property> </property>
<property name="shortcut"> <property name="checked">
<string>Esc</string> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="2"> <item row="10" column="3">
<widget class="QPushButton" name="debug"> <widget class="QPushButton" name="send">
<property name="text"> <property name="text">
<string>&amp;Debug</string> <string>&amp;Execute</string>
</property>
<property name="default">
<bool>false</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="7" column="3">
<widget class="QLabel" name="label5"> <widget class="QSpinBox" name="nonce">
<property name="sizePolicy"> <property name="enabled">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <bool>false</bool>
<horstretch>0</horstretch> </property>
<verstretch>0</verstretch> </widget>
</sizepolicy> </item>
<item row="8" column="0" colspan="4">
<widget class="QSplitter" name="splitter_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QPlainTextEdit" name="data">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
<widget class="QTextEdit" name="code">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QSpinBox" name="value">
<property name="suffix">
<string/>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>0</number>
</property> </property>
</widget>
</item>
<item row="10" column="1">
<widget class="QPushButton" name="copyUnsigned">
<property name="text"> <property name="text">
<string>&amp;To</string> <string>Copy &amp;Unsigned</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QComboBox" name="from"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>&amp;Gas</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>destination</cstring> <cstring>gas</cstring>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="3"> <item row="1" column="0">
<widget class="QComboBox" name="gasPriceUnits"/> <widget class="QLabel" name="label5">
</item>
<item row="7" column="0" colspan="4">
<widget class="QLabel" name="total">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text"> <property name="text">
<string/> <string>&amp;To</string>
</property>
<property name="buddy">
<cstring>destination</cstring>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="10" column="0">
<widget class="QLabel" name="label5_2"> <widget class="QPushButton" name="cancel">
<property name="text"> <property name="text">
<string>&amp;Amount</string> <string>&amp;Cancel</string>
</property> </property>
<property name="buddy"> <property name="shortcut">
<cstring>value</cstring> <string>Esc</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="3"> <item row="7" column="2">
<widget class="QPushButton" name="send"> <widget class="QCheckBox" name="autoNonce">
<property name="text"> <property name="text">
<string>&amp;Execute</string> <string>Auto Nonce</string>
</property> </property>
<property name="default"> <property name="checked">
<bool>true</bool>
</property>
<property name="autoRepeat">
<bool>false</bool> <bool>false</bool>
</property> </property>
</widget> </widget>
@ -111,20 +199,30 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="4" column="2"> <item row="9" column="0" colspan="4">
<widget class="QSpinBox" name="gasPrice"> <widget class="QLabel" name="total">
<property name="prefix"> <property name="sizePolicy">
<string>@ </string> <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<property name="minimum"> <property name="text">
<number>0</number> <string/>
</property> </property>
<property name="maximum"> </widget>
<number>430000000</number> </item>
<item row="3" column="0">
<widget class="QLabel" name="label5_2">
<property name="text">
<string>&amp;Amount</string>
</property>
<property name="buddy">
<cstring>value</cstring>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0"> <item row="7" column="0">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
@ -143,74 +241,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="3">
<widget class="QComboBox" name="valueUnits"/>
</item>
<item row="3" column="1" colspan="2">
<widget class="QSpinBox" name="value">
<property name="suffix">
<string/>
</property>
<property name="maximum">
<number>430000000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="2" column="1" colspan="3">
<widget class="QLineEdit" name="calculatedName">
<property name="enabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string/>
</property>
</widget>
</item>
<item row="6" column="0" colspan="4">
<widget class="QSplitter" name="splitter_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QPlainTextEdit" name="data">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
<widget class="QTextEdit" name="code">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>&amp;Gas</string>
</property>
<property name="buddy">
<cstring>gas</cstring>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
@ -221,43 +251,64 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1" colspan="3"> <item row="4" column="2">
<widget class="QComboBox" name="from"/> <widget class="QSpinBox" name="gasPrice">
</item> <property name="prefix">
<item row="5" column="1"> <string>@ </string>
<widget class="QCheckBox" name="optimize">
<property name="text">
<string>&amp;Optimise</string>
</property> </property>
<property name="checked"> <property name="minimum">
<bool>true</bool> <number>0</number>
</property>
<property name="maximum">
<number>430000000</number>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="3"> <item row="5" column="3">
<widget class="QSpinBox" name="nonce"> <widget class="QSpinBox" name="maxGas">
<property name="enabled"> <property name="suffix">
<bool>false</bool> <string> gas</string>
</property>
<property name="prefix">
<string>max </string>
</property>
<property name="maximum">
<number>450000000</number>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="2"> <item row="5" column="2">
<widget class="QCheckBox" name="autoNonce"> <widget class="QSpinBox" name="minGas">
<property name="text"> <property name="readOnly">
<string>Auto Nonce</string>
</property>
<property name="checked">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="autoRepeat"> <property name="suffix">
<bool>false</bool> <string> gas</string>
</property>
<property name="prefix">
<string>min </string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>450000000</number>
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="1"> <item row="5" column="1">
<widget class="QPushButton" name="copyUnsigned"> <widget class="QProgressBar" name="progressGas">
<property name="text"> <property name="sizePolicy">
<string>Copy &amp;Unsigned</string> <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="value">
<number>24</number>
</property>
<property name="format">
<string>Calculating gas...</string>
</property> </property>
</widget> </widget>
</item> </item>

Loading…
Cancel
Save