diff --git a/CMakeLists.txt b/CMakeLists.txt index 2da01d20f..100ef9139 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") # Normally, set(...CACHE...) creates cache variables, but does not modify them. function(createDefaultCacheConfig) set(VMTRACE OFF CACHE BOOL "VM tracing and run-time checks (useful for cross-implementation VM debugging)") - set(PARANOIA OFF CACHE BOOL "Additional run-time checks") + set(PARANOID OFF CACHE BOOL "Additional run-time checks") set(JSONRPC ON CACHE BOOL "Build with jsonprc. default on") set(FATDB OFF CACHE BOOL "Build with ability to list entries in the Trie. Doubles DB size, slows everything down, but good for looking at state diffs and trie contents.") set(USENPM OFF CACHE BOOL "Use npm to recompile ethereum.js if it was changed") @@ -35,7 +35,7 @@ endfunction() # propagates CMake configuration options to the compiler function(configureProject) - if (PARANOIA) + if (PARANOID) add_definitions(-DETH_PARANOIA) endif () @@ -89,7 +89,7 @@ function(createBuildInfo) set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/int") endif () - if (PARANOIA) + if (PARANOID) set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/PARA") endif () @@ -123,9 +123,9 @@ cmake_policy(SET CMP0015 NEW) # Clear invalid option if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release") - if (PARANOIA) + if (PARANOID) message("Paranoia requires debug - disabling for release build.") - set(PARANOIA OFF) + set(PARANOID OFF) endif () if (VMTRACE) message("VM Tracing requires debug - disabling for release build.") @@ -151,10 +151,10 @@ if (HEADLESS) set(BUNDLE "minimal") endif () -if (PARANOIA) - set(PARANOIA ON) +if (PARANOID) + set(PARANOID ON) else () - set(PARANOIA OFF) + set(PARANOID OFF) endif () if (VMTRACE) set(VMTRACE ON) @@ -282,7 +282,6 @@ message("--------------------------------------------------------------- feature message("-- Chromium support ${ETH_HAVE_WEBENGINE}") message("-- VMTRACE VM execution tracing ${VMTRACE}") message("-- PROFILING Profiling support ${PROFILING}") -message("-- PARANOIA Additional (SLOW) database checking ${PARANOIA}") message("-- FATDB Full database exploring ${FATDB}") message("-- JSONRPC JSON-RPC support ${JSONRPC}") message("-- USENPM Javascript source building ${USENPM}") diff --git a/CodingStandards.txt b/CodingStandards.txt index a98a74c78..bd5cb4ce7 100644 --- a/CodingStandards.txt +++ b/CodingStandards.txt @@ -113,26 +113,33 @@ d. Favour declarations close to use; don't habitually declare at top of scope al e. Always pass non-trivial parameters with a const& suffix. f. If a function returns multiple values, use std::tuple (std::pair acceptable). Prefer not using */& arguments, except where efficiency requires. g. Never use a macro where adequate non-preprocessor C++ can be written. -h. Prefer "using NewType = OldType" to "typedef OldType NewType". -i. Make use of auto whenever type is clear or unimportant: +h. Make use of auto whenever type is clear or unimportant: - Always avoid doubly-stating the type. - Use to avoid vast and unimportant type declarations. +i. Don't pass bools: prefer enumerations instead. +j. Prefer enum class to straight enum. (WRONG) const double d = 0; int i, j; char *s; -float meanAndSigma(std::vector _v, float* _sigma); +float meanAndSigma(std::vector _v, float* _sigma, bool _approximate); Derived* x(dynamic_cast(base)); for (map::iterator i = l.begin(); i != l.end(); ++l) {} + (CORRECT) +enum class Accuracy +{ + Approximate, + Exact +}; double const d = 0; int i; int j; char* s; -std::tuple meanAndSigma(std::vector const& _v); +std::tuple meanAndSigma(std::vector const& _v, Accuracy _a); auto x = dynamic_cast(base); for (auto i = x.begin(); i != x.end(); ++i) {} @@ -192,7 +199,6 @@ c. Where there are exceptions to this (due to excessive use and clear meaning), d. In general expressions should be roughly as important/semantically meaningful as the space they occupy. - 11. Commenting a. Comments should be doxygen-compilable, using @notation rather than \notation. diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index c703c6e95..80788aa22 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -397,7 +397,7 @@ void Client::setupState(State& _s) _s.commitToMine(m_bc); } -ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u256 _gasPrice) +ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u256 _gasPrice, Address const& _from) { ExecutionResult ret; try @@ -407,10 +407,10 @@ ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256 { ReadGuard l(x_stateDB); temp = m_postMine; - temp.addBalance(Address(), _value + _gasPrice * _gas); + temp.addBalance(_from, _value + _gasPrice * _gas); } Executive e(temp, LastHashes(), 0); - if (!e.call(_dest, _dest, Address(), _value, _gasPrice, &_data, _gas, Address())) + if (!e.call(_dest, _dest, _from, _value, _gasPrice, &_data, _gas, _from)) e.go(); ret = e.executionResult(); } diff --git a/libethereum/Client.h b/libethereum/Client.h index bdd875e95..25a087de0 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -159,7 +159,7 @@ public: using Interface::call; // to remove warning about hiding virtual function /// Makes the given call. Nothing is recorded into the state. This cheats by creating a null address and endowing it with a lot of ETH. - ExecutionResult call(Address _dest, bytes const& _data = bytes(), u256 _gas = 125000, u256 _value = 0, u256 _gasPrice = 1 * ether); + ExecutionResult call(Address _dest, bytes const& _data = bytes(), u256 _gas = 125000, u256 _value = 0, u256 _gasPrice = 1 * ether, Address const& _from = Address()); /// Get the remaining gas limit in this block. virtual u256 gasLimitRemaining() const { return m_postMine.gasLimitRemaining(); } diff --git a/libethereum/ClientBase.cpp b/libethereum/ClientBase.cpp index d1d9bc27f..1d27bcfce 100644 --- a/libethereum/ClientBase.cpp +++ b/libethereum/ClientBase.cpp @@ -65,14 +65,17 @@ Address ClientBase::submitTransaction(Secret _secret, u256 _endowment, bytes con } // TODO: remove try/catch, allow exceptions -ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) +ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff) { ExecutionResult ret; try { State temp = asOf(_blockNumber); - u256 n = temp.transactionsFrom(toAddress(_secret)); + Address a = toAddress(_secret); + u256 n = temp.transactionsFrom(a); Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); + if (_ff == FudgeFactor::Lenient) + temp.addBalance(a, (u256)(t.gasRequired() * t.gasPrice() + t.value())); ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted); } catch (...) @@ -82,16 +85,19 @@ ExecutionResult ClientBase::call(Secret _secret, u256 _value, Address _dest, byt return ret; } -ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) +ExecutionResult ClientBase::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff) { ExecutionResult ret; try { State temp = asOf(_blockNumber); - u256 n = temp.transactionsFrom(toAddress(_secret)); + Address a = toAddress(_secret); + u256 n = temp.transactionsFrom(a); // cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); Transaction t(_value, _gasPrice, _gas, _data, n, _secret); + if (_ff == FudgeFactor::Lenient) + temp.addBalance(a, (u256)(t.gasRequired() * t.gasPrice() + t.value())); ret = temp.execute(bc().lastHashes(), t, Permanence::Reverted); } catch (...) diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index 2d5b4a802..d06904b5d 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -82,9 +82,10 @@ public: virtual Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo) override; /// Makes the given call. Nothing is recorded into the state. - virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock) override; + virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock, FudgeFactor _ff = FudgeFactor::Strict) override; - virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock) override; + /// Makes the given create. Nothing is recorded into the state. + virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, BlockNumber _blockNumber = PendingBlock, FudgeFactor _ff = FudgeFactor::Strict) override; using Interface::balanceAt; using Interface::countAt; diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 0151a8ccb..ac41b0ec1 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -46,6 +46,12 @@ enum class Reaping Manual }; +enum class FudgeFactor +{ + Strict, + Lenient +}; + /** * @brief Main API hub for interfacing with Ethereum. */ @@ -71,13 +77,13 @@ public: virtual void flushTransactions() = 0; /// Makes the given call. Nothing is recorded into the state. - virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) = 0; - ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) { return call(_secret, _value, _dest, _data, _gas, _gasPrice, m_default); } + virtual ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0; + ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, FudgeFactor _ff = FudgeFactor::Strict) { return call(_secret, _value, _dest, _data, _gas, _gasPrice, m_default, _ff); } /// Does the given creation. Nothing is recorded into the state. /// @returns the pair of the Address of the created contract together with its code. - virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) = 0; - ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo) { return create(_secret, _value, _data, _gas, _gasPrice, m_default); } + virtual ExecutionResult create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0; + ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo, FudgeFactor _ff = FudgeFactor::Strict) { return create(_secret, _value, _data, _gas, _gasPrice, m_default, _ff); } // [STATE-QUERY API] diff --git a/libethereum/State.cpp b/libethereum/State.cpp index fcd223661..5631ffe28 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -543,8 +543,6 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce) // m_currentBlock is assumed to be prepopulated and reset. BlockInfo bi(_block, _checkNonce ? CheckEverything : IgnoreNonce); - cdebug << "enacting" << BlockInfo::headerHash(_block).abridged() << "==" << bi.hash().abridged() << "on" << m_previousBlock.hash().abridged(); - cdebug << m_currentBlock; #if !ETH_RELEASE assert(m_previousBlock.hash() == bi.parentHash); @@ -560,9 +558,6 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce) m_currentBlock.verifyInternals(_block); m_currentBlock.noteDirty(); - cdebug << "populated and verified. incoming block hash is" << m_currentBlock.hash().abridged(); - cdebug << m_currentBlock; - // cnote << "playback begins:" << m_state.root(); // cnote << m_state; @@ -631,7 +626,6 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce) // Initialise total difficulty calculation. u256 tdIncrease = m_currentBlock.difficulty; - // Check uncles & apply their rewards to state. if (rlp[2].itemCount() > 2) BOOST_THROW_EXCEPTION(TooManyUncles()); @@ -686,11 +680,6 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce) BOOST_THROW_EXCEPTION(InvalidGasUsed() << RequirementError(bigint(gasUsed()), bigint(m_currentBlock.gasUsed))); } - cdebug << m_currentBlock; - auto hh = m_currentBlock.hash(); - m_currentBlock.noteDirty(); - cdebug << "done enacting. new stateroot is" << m_currentBlock.stateRoot.abridged() << ", hash is" << m_currentBlock.hash().abridged() << " = " << hh; - return tdIncrease; } diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index 072d96331..291415a68 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -497,12 +497,13 @@ string WebThreeStubServerBase::eth_call(Json::Value const& _json, string const& string ret; if (!t.from) t.from = m_accounts->getDefaultTransactAccount(); - if (!m_accounts->isRealAccount(t.from)) - return ret; +// if (!m_accounts->isRealAccount(t.from)) +// return ret; if (!t.gasPrice) t.gasPrice = 10 * dev::eth::szabo; if (!t.gas) - t.gas = min(client()->gasLimitRemaining(), client()->balanceAt(t.from) / t.gasPrice); + t.gas = client()->gasLimitRemaining(); + ret = toJS(client()->call(m_accounts->secretKey(t.from), t.value, t.to, t.data, t.gas, t.gasPrice, number).output); return ret; diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 60d97e5b7..ff35a6d78 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -295,12 +295,15 @@ Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes cons return address; } -dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto) +dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto, FudgeFactor _ff) { (void)_blockNumber; + Address a = toAddress(_secret); State temp = asOf(eth::PendingBlock); - u256 n = temp.transactionsFrom(toAddress(_secret)); + u256 n = temp.transactionsFrom(a); Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); + if (_ff == FudgeFactor::Lenient) + temp.addBalance(a, (u256)(t.gasRequired() * t.gasPrice() + t.value())); bytes rlp = t.rlp(); WriteGuard lw(x_state); //TODO: lock is required only for last execution state executeTransaction(t, temp, true, _gasAuto, _secret); @@ -317,22 +320,25 @@ Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes cons return submitTransaction(_secret, _endowment, _init, _gas, _gasPrice, false); } -dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) +dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, eth::FudgeFactor _ff) { - return call(_secret, _value, _dest, _data, _gas, _gasPrice, _blockNumber,false); + return call(_secret, _value, _dest, _data, _gas, _gasPrice, _blockNumber, false, _ff); } -dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) +dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, eth::FudgeFactor _ff) { (void)_blockNumber; u256 n; + Address a = toAddress(_secret); State temp; { ReadGuard lr(x_state); temp = asOf(eth::PendingBlock); - n = temp.transactionsFrom(toAddress(_secret)); + n = temp.transactionsFrom(a); } Transaction t(_value, _gasPrice, _gas, _data, n, _secret); + if (_ff == FudgeFactor::Lenient) + temp.addBalance(a, (u256)(t.gasRequired() * t.gasPrice() + t.value())); bytes rlp = t.rlp(); WriteGuard lw(x_state); //TODO: lock is required only for last execution state executeTransaction(t, temp, true, false, _secret); diff --git a/mix/MixClient.h b/mix/MixClient.h index c52e7bd88..480509545 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -55,12 +55,12 @@ public: void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) override; Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) override; - dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber = eth::PendingBlock) override; - dev::eth::ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * eth::szabo, eth::BlockNumber _blockNumber = eth::PendingBlock) override; + dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override; + dev::eth::ExecutionResult create(Secret _secret, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * eth::szabo, eth::BlockNumber _blockNumber = eth::PendingBlock, eth::FudgeFactor _ff = eth::FudgeFactor::Strict) override; void submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, bool _gasAuto); Address submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice, bool _gasAuto); - dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber, bool _gasAuto); + dev::eth::ExecutionResult call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, eth::BlockNumber _blockNumber, bool _gasAuto, eth::FudgeFactor _ff = eth::FudgeFactor::Strict); void setAddress(Address _us) override; void setMiningThreads(unsigned _threads) override;