From 13d77a34e50db29913df9af8a4ffc125155c16ac Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 31 Mar 2015 09:20:36 +0200 Subject: [PATCH 1/3] Avoid asserting until I know exactly what ethash_quick_check_difficulty is meant to do. --- libethcore/Ethasher.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/libethcore/Ethasher.cpp b/libethcore/Ethasher.cpp index 79a2fdea3..880bc139a 100644 --- a/libethcore/Ethasher.cpp +++ b/libethcore/Ethasher.cpp @@ -112,17 +112,24 @@ bool Ethasher::verify(BlockInfo const& _header) h256 boundary = u256((bigint(1) << 256) / _header.difficulty); - bool ret = ethash_quick_check_difficulty( + bool quick = ethash_quick_check_difficulty( _header.headerHash(WithoutNonce).data(), (uint64_t)(u64)_header.nonce, _header.mixHash.data(), boundary.data()); -#if ETH_DEBUG +#if !ETH_DEBUG + if (!quick) + return false; +#endif + auto result = eval(_header); - if ((result.value <= boundary && result.mixHash == _header.mixHash) != ret) + bool slow = result.value <= boundary && result.mixHash == _header.mixHash; + +#if ETH_DEBUG + if (!quick && slow) { - cwarn << "Assertion failure coming: evaluated result gives different outcome to ethash_quick_check_difficulty"; + cwarn << "WARNING: evaluated result gives true whereas ethash_quick_check_difficulty gives false."; cwarn << "headerHash:" << _header.headerHash(WithoutNonce); cwarn << "nonce:" << _header.nonce; cwarn << "mixHash:" << _header.mixHash; @@ -131,12 +138,9 @@ bool Ethasher::verify(BlockInfo const& _header) cwarn << "result.value:" << result.value; cwarn << "result.mixHash:" << result.mixHash; } - assert((result.value <= boundary) == ret); - if (result.value <= boundary) - assert(result.mixHash == _header.mixHash); #endif - return ret; + return slow; } Ethasher::Result Ethasher::eval(BlockInfo const& _header, Nonce const& _nonce) From b28a600b33a0d9342ab03ee7c59cc7c5c6d8ee78 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 31 Mar 2015 09:50:04 +0200 Subject: [PATCH 2/3] Fixes #1470 --- libwhisper/Message.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libwhisper/Message.cpp b/libwhisper/Message.cpp index 07bcea0c1..4375e0727 100644 --- a/libwhisper/Message.cpp +++ b/libwhisper/Message.cpp @@ -58,10 +58,10 @@ Message::Message(Envelope const& _e, FullTopic const& _fk, Secret const& _s) // get key from decrypted topic key: just xor h256 tk = h256(bytesConstRef(&(_e.data())).cropped(32 * topicIndex, 32)); bytesConstRef cipherText = bytesConstRef(&(_e.data())).cropped(32 * _e.topic().size()); - cnote << "Decrypting(" << topicIndex << "): " << topicSecret << tk << (topicSecret ^ tk) << toHex(cipherText); +// cdebug << "Decrypting(" << topicIndex << "): " << topicSecret << tk << (topicSecret ^ tk) << toHex(cipherText); if (!decryptSym(topicSecret ^ tk, cipherText, b)) return; - cnote << "Got: " << toHex(b); +// cdebug << "Got: " << toHex(b); } if (populate(b)) From 62b4958952f084fbb45061a5dc6d11b0c6a3e753 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 31 Mar 2015 10:07:13 +0200 Subject: [PATCH 3/3] 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; }