From 62b4958952f084fbb45061a5dc6d11b0c6a3e753 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 31 Mar 2015 10:07:13 +0200 Subject: [PATCH] Provide a little more information on why things might fail. --- alethzero/Transact.cpp | 2 +- libethcore/Params.h | 6 +++--- libethereum/Executive.cpp | 5 ++++- libethereum/Executive.h | 2 ++ libethereum/Transaction.cpp | 8 ++++---- libethereum/Transaction.h | 27 ++++++++++++++++++++------- 6 files changed, 34 insertions(+), 16 deletions(-) diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index 6f52548c7..1ff3427e3 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -338,7 +338,7 @@ void Transact::rejigData() } if (er.codeDeposit == CodeDeposit::Failed) { - bail("
ERROR Code deposit failed due to insufficient gas
"); + bail("
ERROR Code deposit failed due to insufficient gas; " + QString::fromStdString(toString(er.gasForDeposit)) + " GAS < " + QString::fromStdString(toString(er.depositSize)) + " bytes * " + QString::fromStdString(toString(c_createDataGas)) + "GAS/byte
"); return; } diff --git a/libethcore/Params.h b/libethcore/Params.h index 7520e49f1..62cf6b2d8 100644 --- a/libethcore/Params.h +++ b/libethcore/Params.h @@ -29,15 +29,15 @@ namespace eth { //--- BEGIN: AUTOGENERATED FROM /feeStructure.json -extern u256 const c_genesisDifficulty; -extern u256 const c_maximumExtraDataSize; -extern u256 const c_epochDuration; extern u256 const c_genesisGasLimit; extern u256 const c_minGasLimit; extern u256 const c_gasLimitBoundDivisor; +extern u256 const c_genesisDifficulty; extern u256 const c_minimumDifficulty; extern u256 const c_difficultyBoundDivisor; extern u256 const c_durationLimit; +extern u256 const c_maximumExtraDataSize; +extern u256 const c_epochDuration; extern u256 const c_stackLimit; extern u256 const c_tierStepGas[8]; ///< Once per operation, for a selection of them. diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index dfd526bef..0b75a07af 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -46,7 +46,7 @@ u256 Executive::gasUsed() const ExecutionResult Executive::executionResult() const { - return ExecutionResult(gasUsed(), m_excepted, m_newAddress, m_out, m_codeDeposit, m_ext ? m_ext->sub.refunds : 0); + return ExecutionResult(gasUsed(), m_excepted, m_newAddress, m_out, m_codeDeposit, m_ext ? m_ext->sub.refunds : 0, m_depositSize, m_gasForDeposit); } void Executive::accrueSubState(SubState& _parentContext) @@ -221,6 +221,8 @@ bool Executive::go(OnOpFunc const& _onOp) if (m_isCreation) { + m_gasForDeposit = m_endGas; + m_depositSize = m_out.size(); if (m_out.size() * c_createDataGas <= m_endGas) { m_codeDeposit = CodeDeposit::Success; @@ -228,6 +230,7 @@ bool Executive::go(OnOpFunc const& _onOp) } else { + m_codeDeposit = CodeDeposit::Failed; m_out.reset(); } diff --git a/libethereum/Executive.h b/libethereum/Executive.h index 3445ad407..158e86330 100644 --- a/libethereum/Executive.h +++ b/libethereum/Executive.h @@ -128,6 +128,8 @@ private: unsigned m_depth = 0; ///< The context's call-depth. bool m_isCreation = false; ///< True if the transaction creates a contract, or if create() is called. + unsigned m_depositSize = 0; ///< Amount of code of the creation's attempted deposit. + u256 m_gasForDeposit; ///< Amount of gas remaining for the code deposit phase. CodeDeposit m_codeDeposit = CodeDeposit::None; ///< True if an attempted deposit failed due to lack of gas. TransactionException m_excepted = TransactionException::None; ///< Details if the VM's execution resulted in an exception. u256 m_endGas; ///< The final amount of gas for the transaction. diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp index 502f089fb..3228eca70 100644 --- a/libethereum/Transaction.cpp +++ b/libethereum/Transaction.cpp @@ -88,12 +88,12 @@ Transaction::Transaction(bytesConstRef _rlpData, CheckSignature _checkSig) } catch (Exception& _e) { - _e << errinfo_name("invalid transaction format") << BadFieldError(field,toHex(rlp[field].data().toBytes())); + _e << errinfo_name("invalid transaction format") << BadFieldError(field, toHex(rlp[field].data().toBytes())); throw; } } -Address Transaction::safeSender() const noexcept +Address const& Transaction::safeSender() const noexcept { try { @@ -102,11 +102,11 @@ Address Transaction::safeSender() const noexcept catch (...) { cwarn << "safeSender() did throw an exception: " << boost::current_exception_diagnostic_information(); - return Address(); + return NullAddress; } } -Address Transaction::sender() const +Address const& Transaction::sender() const { if (!m_sender) { diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h index bed291868..ab2c12b50 100644 --- a/libethereum/Transaction.h +++ b/libethereum/Transaction.h @@ -75,17 +75,30 @@ TransactionException toTransactionException(VMException const& _e); struct ExecutionResult { ExecutionResult() = default; - ExecutionResult(u256 _gasUsed, TransactionException _excepted, Address _newAddress, bytesConstRef _output, CodeDeposit _codeDeposit, u256 _gasRefund): gasUsed(_gasUsed), excepted(_excepted), newAddress(_newAddress), output(_output.toBytes()), codeDeposit(_codeDeposit), gasRefunded(_gasRefund) {} + ExecutionResult(u256 const& _gasUsed, TransactionException _excepted, Address const& _newAddress, bytesConstRef _output, CodeDeposit _codeDeposit, u256 const& _gasRefund, unsigned _depositSize, u256 const& _gasForDeposit): + gasUsed(_gasUsed), + excepted(_excepted), + newAddress(_newAddress), + output(_output.toBytes()), + codeDeposit(_codeDeposit), + gasRefunded(_gasRefund), + depositSize(_depositSize), + gasForDeposit(_gasForDeposit) + {} u256 gasUsed = 0; TransactionException excepted = TransactionException::Unknown; Address newAddress; bytes output; CodeDeposit codeDeposit = CodeDeposit::None; u256 gasRefunded = 0; + unsigned depositSize = 0; + u256 gasForDeposit; }; std::ostream& operator<<(std::ostream& _out, ExecutionResult const& _er); +static const Address NullAddress; + /// Encodes a transaction, ready to be exported to or freshly imported from RLP. class Transaction { @@ -94,16 +107,16 @@ public: Transaction() {} /// Constructs a signed message-call transaction. - Transaction(u256 _value, u256 _gasPrice, u256 _gas, Address const& _dest, bytes const& _data, u256 _nonce, Secret const& _secret): m_type(MessageCall), m_nonce(_nonce), m_value(_value), m_receiveAddress(_dest), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) { sign(_secret); } + Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data, u256 const& _nonce, Secret const& _secret): m_type(MessageCall), m_nonce(_nonce), m_value(_value), m_receiveAddress(_dest), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) { sign(_secret); } /// Constructs a signed contract-creation transaction. - Transaction(u256 _value, u256 _gasPrice, u256 _gas, bytes const& _data, u256 _nonce, Secret const& _secret): m_type(ContractCreation), m_nonce(_nonce), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) { sign(_secret); } + Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data, u256 const& _nonce, Secret const& _secret): m_type(ContractCreation), m_nonce(_nonce), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) { sign(_secret); } /// Constructs an unsigned message-call transaction. - Transaction(u256 _value, u256 _gasPrice, u256 _gas, Address const& _dest, bytes const& _data): m_type(MessageCall), m_value(_value), m_receiveAddress(_dest), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {} + Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, Address const& _dest, bytes const& _data): m_type(MessageCall), m_value(_value), m_receiveAddress(_dest), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {} /// Constructs an unsigned contract-creation transaction. - Transaction(u256 _value, u256 _gasPrice, u256 _gas, bytes const& _data): m_type(ContractCreation), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {} + Transaction(u256 const& _value, u256 const& _gasPrice, u256 const& _gas, bytes const& _data): m_type(ContractCreation), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {} /// Constructs a transaction from the given RLP. explicit Transaction(bytesConstRef _rlp, CheckSignature _checkSig); @@ -118,9 +131,9 @@ public: bool operator!=(Transaction const& _c) const { return !operator==(_c); } /// @returns sender of the transaction from the signature (and hash). - Address sender() const; + Address const& sender() const; /// Like sender() but will never throw. @returns a null Address if the signature is invalid. - Address safeSender() const noexcept; + Address const& safeSender() const noexcept; /// @returns true if transaction is non-null. explicit operator bool() const { return m_type != NullTransaction; }