Browse Source

First dubby impl.

cl-refactor
Gav Wood 9 years ago
parent
commit
9e40a05be1
  1. 160
      alethzero/Transact.cpp
  2. 11
      alethzero/Transact.h
  3. 305
      alethzero/Transact.ui

160
alethzero/Transact.cpp

@ -64,6 +64,8 @@ Transact::Transact(MainFace* _c, QWidget* _parent):
setValueUnits(ui->valueUnits, ui->value, 0);
on_destination_currentTextChanged(QString());
startTimer(100);
}
Transact::~Transact()
@ -334,6 +336,96 @@ pair<Address, bytes> Transact::toAccount()
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 = mid;
else
{
m_lastGood = er;
m_upperBound = 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);
}
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};
QString 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);
auto bail = [&](QString he) {
m_allGood = false;
// ui->send->setEnabled(false);
ui->code->setHtml(he + htmlInfo + ui->code->toHtml());
};
auto s = fromAccount();
auto b = ethereum()->balanceAt(s, PendingBlock);
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;
}
// 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());
killTimer(m_gasCalcTimer);
}
GasRequirements Transact::determineGasRequirements()
{
// Determine the minimum amount of gas we need to play...
@ -343,12 +435,11 @@ GasRequirements Transact::determineGasRequirements()
Address to = toAccount().first;
ExecutionResult lastGood;
bool haveUpperBound = false;
qint64 lowerBound = baseGas;
qint64 upperBound = (qint64)ethereum()->gasLimitRemaining();
for (unsigned i = 0; i < 30 && ((haveUpperBound && upperBound - lowerBound > 16) || !haveUpperBound); ++i) // get to with 100.
m_startLowerBound = baseGas;
m_startUpperBound = (qint64)ethereum()->gasLimitRemaining();
for (unsigned i = 0; i < 30; ++i)
{
qint64 mid = haveUpperBound ? (lowerBound + upperBound) / 2 : upperBound;
qint64 mid = m_startUpperBound;
ExecutionResult er;
if (isCreation())
er = ethereum()->create(from, value(), m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient);
@ -356,23 +447,19 @@ GasRequirements Transact::determineGasRequirements()
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)
{
lowerBound = mid;
if (!haveUpperBound)
upperBound *= 2;
m_startLowerBound = mid;
m_startUpperBound *= 2;
}
else
{
lastGood = er;
if (haveUpperBound)
upperBound = mid;
else
haveUpperBound = true;
m_lastGood = lastGood;
m_lowerBound = m_startLowerBound;
m_upperBound = m_startUpperBound;
startTimer(0);
return GasRequirements{m_upperBound, baseGas, m_upperBound - baseGas, (qint64)lastGood.gasRefunded, lastGood};
}
}
// 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};
return GasRequirements();
}
void Transact::rejigData()
@ -386,8 +473,6 @@ void Transact::rejigData()
if (!s)
return;
auto b = ethereum()->balanceAt(s, PendingBlock);
m_allGood = true;
QString htmlInfo;
@ -422,46 +507,11 @@ void Transact::rejigData()
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
if (!isCreation())
htmlInfo = "<div class=\"info\"><span class=\"icon\">INFO</span> " + QString::fromStdString(natspecNotice(toAccount().first, m_data)).toHtmlEscaped() + "</div>" + htmlInfo;
// 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();
determineGasRequirements();
ui->code->setHtml(htmlInfo);
// ui->send->setEnabled(m_allGood);

11
alethzero/Transact.h

@ -79,6 +79,8 @@ private:
dev::eth::Client* ethereum() const { return m_ethereum; }
void rejigData();
void updateNonce();
void updateBounds();
void finaliseBounds();
dev::Address fromAccount();
std::pair<dev::Address, bytes> toAccount();
@ -95,6 +97,8 @@ private:
std::string natspecNotice(dev::Address _to, dev::bytes const& _data);
dev::Secret findSecret(dev::u256 _totalReq) const;
void timerEvent(QTimerEvent*) override;
Ui::Transact* ui = nullptr;
unsigned m_backupGas = 0;
@ -106,7 +110,12 @@ private:
NatSpecFace* m_natSpecDB = nullptr;
bool m_allGood = false;
bool m_determiningGas = false;
qint64 m_startLowerBound = 0;
qint64 m_startUpperBound = 0;
qint64 m_lowerBound = 0;
qint64 m_upperBound = 0;
eth::ExecutionResult m_lastGood;
int m_gasCalcTimer = 0;
};
}

305
alethzero/Transact.ui

@ -14,6 +14,13 @@
<string>Transact</string>
</property>
<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">
<widget class="QSpinBox" name="gas">
<property name="suffix">
@ -30,71 +37,149 @@
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QPushButton" name="cancel">
<item row="3" column="3">
<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">
<string>&amp;Cancel</string>
<string>&amp;Optimise</string>
</property>
<property name="shortcut">
<string>Esc</string>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="QPushButton" name="debug">
<item row="10" column="3">
<widget class="QPushButton" name="send">
<property name="text">
<string>&amp;Debug</string>
<string>&amp;Execute</string>
</property>
<property name="default">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="7" column="3">
<widget class="QSpinBox" name="nonce">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</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>
</widget>
</item>
<item row="10" column="1">
<widget class="QPushButton" name="copyUnsigned">
<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 name="buddy">
<cstring>destination</cstring>
<cstring>gas</cstring>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QComboBox" name="gasPriceUnits"/>
</item>
<item row="7" column="0" colspan="4">
<widget class="QLabel" name="total">
<item row="1" column="0">
<widget class="QLabel" name="label5">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
<string>&amp;To</string>
</property>
<property name="buddy">
<cstring>destination</cstring>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label5_2">
<item row="10" column="0">
<widget class="QPushButton" name="cancel">
<property name="text">
<string>&amp;Amount</string>
<string>&amp;Cancel</string>
</property>
<property name="buddy">
<cstring>value</cstring>
<property name="shortcut">
<string>Esc</string>
</property>
</widget>
</item>
<item row="8" column="3">
<widget class="QPushButton" name="send">
<item row="7" column="2">
<widget class="QCheckBox" name="autoNonce">
<property name="text">
<string>&amp;Execute</string>
<string>Auto Nonce</string>
</property>
<property name="default">
<property name="checked">
<bool>true</bool>
</property>
<property name="autoRepeat">
<bool>false</bool>
</property>
</widget>
@ -111,20 +196,30 @@
</item>
</widget>
</item>
<item row="4" column="2">
<widget class="QSpinBox" name="gasPrice">
<property name="prefix">
<string>@ </string>
<item row="9" column="0" colspan="4">
<widget class="QLabel" name="total">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum">
<number>0</number>
<property name="text">
<string/>
</property>
<property name="maximum">
<number>430000000</number>
</widget>
</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>
</widget>
</item>
<item row="5" column="0">
<item row="7" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
@ -143,74 +238,6 @@
</property>
</widget>
</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">
<widget class="QLabel" name="label">
<property name="text">
@ -221,43 +248,49 @@
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QComboBox" name="from"/>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="optimize">
<property name="text">
<string>&amp;Optimise</string>
<item row="4" column="2">
<widget class="QSpinBox" name="gasPrice">
<property name="prefix">
<string>@ </string>
</property>
<property name="checked">
<bool>true</bool>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>430000000</number>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="QSpinBox" name="nonce">
<property name="enabled">
<bool>false</bool>
<item row="6" column="1">
<widget class="QSpinBox" name="minGas">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="suffix">
<string> gas</string>
</property>
<property name="prefix">
<string>min </string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QCheckBox" name="autoNonce">
<property name="text">
<string>Auto Nonce</string>
<item row="6" column="3">
<widget class="QProgressBar" name="progressGas">
<property name="value">
<number>24</number>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="autoRepeat">
<bool>false</bool>
<property name="format">
<string>Calculating gas...</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QPushButton" name="copyUnsigned">
<property name="text">
<string>Copy &amp;Unsigned</string>
<item row="6" column="2">
<widget class="QSpinBox" name="maxGas">
<property name="suffix">
<string> gas</string>
</property>
<property name="prefix">
<string>max </string>
</property>
</widget>
</item>

Loading…
Cancel
Save