Browse Source

Merge remote-tracking branch 'upstream/develop' into refactor_executive

cl-refactor
Paweł Bylica 10 years ago
parent
commit
e34efb39d6
  1. 12
      alethzero/MainWin.cpp
  2. 2
      alethzero/MainWin.h
  3. 6
      alethzero/NatspecHandler.h
  4. 2
      alethzero/Transact.cpp
  5. 195
      eth/main.cpp
  6. 39
      ethkey/KeyAux.h
  7. 7
      ethminer/CMakeLists.txt
  8. 7
      ethminer/MinerAux.h
  9. 5
      json_spirit/json_spirit_writer_template.h
  10. 2
      libdevcore/Common.cpp
  11. 52
      libdevcore/CommonData.cpp
  12. 2
      libdevcore/CommonData.h
  13. 39
      libdevcore/Exceptions.h
  14. 2
      libdevcore/FixedHash.h
  15. 8
      libdevcore/Log.cpp
  16. 3
      libdevcore/Log.h
  17. 8
      libdevcore/RangeMask.h
  18. 4
      libdevcrypto/Common.cpp
  19. 2
      libdevcrypto/CryptoPP.cpp
  20. 2
      libdevcrypto/CryptoPP.h
  21. 4
      libdevcrypto/OverlayDB.cpp
  22. 2
      libdevcrypto/SecretStore.cpp
  23. 51
      libethash-cl/ethash_cl_miner.cpp
  24. 5
      libethash-cl/ethash_cl_miner.h
  25. 24
      libethcore/BlockInfo.cpp
  26. 15
      libethcore/Ethash.cpp
  27. 6
      libethcore/Ethash.h
  28. 77
      libethcore/Exceptions.h
  29. 23
      libethcore/KeyManager.cpp
  30. 11
      libethcore/KeyManager.h
  31. 48
      libethereum/BlockChain.cpp
  32. 5
      libethereum/BlockChain.h
  33. 55
      libethereum/BlockQueue.cpp
  34. 4
      libethereum/BlockQueue.h
  35. 7
      libethereum/CMakeLists.txt
  36. 167
      libethereum/Client.cpp
  37. 35
      libethereum/Client.h
  38. 5
      libethereum/ClientBase.cpp
  39. 8
      libethereum/ClientBase.h
  40. 13
      libethereum/CommonNet.h
  41. 7
      libethereum/DownloadMan.cpp
  42. 8
      libethereum/DownloadMan.h
  43. 113
      libethereum/EthereumHost.cpp
  44. 16
      libethereum/EthereumHost.h
  45. 37
      libethereum/EthereumPeer.cpp
  46. 15
      libethereum/EthereumPeer.h
  47. 118
      libethereum/Executive.cpp
  48. 18
      libethereum/Executive.h
  49. 2
      libethereum/Interface.h
  50. 8
      libethereum/Precompiled.cpp
  51. 31
      libethereum/Sentinel.h
  52. 3
      libethereum/Sentinel.json
  53. 157
      libethereum/State.cpp
  54. 28
      libethereum/State.h
  55. 43
      libethereum/Transaction.cpp
  56. 6
      libethereum/Transaction.h
  57. 322
      libevm/VM.cpp
  58. 6
      libevm/VM.h
  59. 1
      libevm/VMFace.h
  60. 2
      libevmasm/Assembly.cpp
  61. 4
      libevmcore/Exceptions.h
  62. 4
      libp2p/Common.h
  63. 4
      libp2p/Host.cpp
  64. 2
      libp2p/Network.cpp
  65. 12
      libp2p/NodeTable.cpp
  66. 4
      libp2p/RLPxFrameIO.cpp
  67. 4
      libp2p/UDP.cpp
  68. 2
      libp2p/UDP.h
  69. 42
      libsolidity/AST.cpp
  70. 2
      libsolidity/AST.h
  71. 2
      libsolidity/CompilerContext.cpp
  72. 2
      libsolidity/LValue.h
  73. 12
      libsolidity/Types.cpp
  74. 4
      libsolidity/Types.h
  75. 2
      libtestutils/FixedClient.h
  76. 2
      libweb3jsonrpc/WebThreeStubServer.h
  77. 18
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  78. 3
      libweb3jsonrpc/WebThreeStubServerBase.h
  79. 14
      libweb3jsonrpc/abstractwebthreestubserver.h
  80. 3
      libweb3jsonrpc/spec.json
  81. 8
      libwhisper/WhisperHost.h
  82. 4
      mix/ClientModel.cpp
  83. 2
      mix/CodeModel.cpp
  84. 44
      mix/MixClient.cpp
  85. 2
      mix/MixClient.h
  86. BIN
      mix/qml/img/addblock.png
  87. BIN
      mix/qml/img/addblock@2x.png
  88. BIN
      mix/qml/img/duplicateicon.png
  89. BIN
      mix/qml/img/duplicateicon@2x.png
  90. BIN
      mix/qml/img/leftarrow.png
  91. BIN
      mix/qml/img/leftarrow@2x.png
  92. BIN
      mix/qml/img/newaccounticon.png
  93. BIN
      mix/qml/img/newaccounticon@2x.png
  94. BIN
      mix/qml/img/recyclediscard.png
  95. BIN
      mix/qml/img/recyclediscard@2x.png
  96. BIN
      mix/qml/img/recycleicon.png
  97. BIN
      mix/qml/img/recycleicon@2x.png
  98. BIN
      mix/qml/img/recyclekeep.png
  99. BIN
      mix/qml/img/recyclekeep@2x.png
  100. BIN
      mix/qml/img/restoreicon.png

12
alethzero/MainWin.cpp

@ -1240,7 +1240,9 @@ void Main::refreshBlockCount()
{
auto d = ethereum()->blockChain().details();
BlockQueueStatus b = ethereum()->blockQueueStatus();
ui->chainStatus->setText(QString("%3 ready %4 verifying %5 unverified %6 future %7 unknown %8 bad %1 #%2").arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet").arg(d.number).arg(b.verified).arg(b.verifying).arg(b.unverified).arg(b.future).arg(b.unknown).arg(b.bad));
HashChainStatus h = ethereum()->hashChainStatus();
ui->chainStatus->setText(QString("%9/%10%11 hashes %3 ready %4 verifying %5 unverified %6 future %7 unknown %8 bad %1 #%2")
.arg(m_privateChain.size() ? "[" + m_privateChain + "] " : "testnet").arg(d.number).arg(b.verified).arg(b.verifying).arg(b.unverified).arg(b.future).arg(b.unknown).arg(b.bad).arg(h.received).arg(h.estimated ? "~" : "").arg(h.total));
}
void Main::on_turboMining_triggered()
@ -2114,14 +2116,14 @@ void Main::on_reencryptKey_triggered()
auto pw = [&](){
auto p = QInputDialog::getText(this, "Re-Encrypt Key", "Enter the original password for this key.\nHint: " + QString::fromStdString(m_keyManager.hint(a)), QLineEdit::Password, QString()).toStdString();
if (p.empty())
throw UnknownPassword();
throw PasswordUnknown();
return p;
};
while (!(password.empty() ? m_keyManager.recode(a, SemanticPassword::Master, pw, kdf) : m_keyManager.recode(a, password, hint, pw, kdf)))
if (QMessageBox::question(this, "Re-Encrypt Key", "Password given is incorrect. Would you like to try again?", QMessageBox::Retry, QMessageBox::Cancel) == QMessageBox::Cancel)
return;
}
catch (UnknownPassword&) {}
catch (PasswordUnknown&) {}
}
}
@ -2137,13 +2139,13 @@ void Main::on_reencryptAll_triggered()
while (!m_keyManager.recode(a, SemanticPassword::Existing, [&](){
auto p = QInputDialog::getText(nullptr, "Re-Encrypt Key", QString("Enter the original password for key %1.\nHint: %2").arg(QString::fromStdString(pretty(a))).arg(QString::fromStdString(m_keyManager.hint(a))), QLineEdit::Password, QString()).toStdString();
if (p.empty())
throw UnknownPassword();
throw PasswordUnknown();
return p;
}, (KDF)kdfs.indexOf(kdf)))
if (QMessageBox::question(this, "Re-Encrypt Key", "Password given is incorrect. Would you like to try again?", QMessageBox::Retry, QMessageBox::Cancel) == QMessageBox::Cancel)
return;
}
catch (UnknownPassword&) {}
catch (PasswordUnknown&) {}
}
void Main::on_go_triggered()

2
alethzero/MainWin.h

@ -238,7 +238,7 @@ private:
void installNameRegWatch();
void installBalancesWatch();
virtual void timerEvent(QTimerEvent*);
virtual void timerEvent(QTimerEvent*) override;
void refreshNetwork();
void refreshMining();

6
alethzero/NatspecHandler.h

@ -39,17 +39,17 @@ class NatspecHandler: public NatSpecFace
~NatspecHandler();
/// Stores locally in a levelDB a key value pair of contract code hash to natspec documentation
void add(dev::h256 const& _contractHash, std::string const& _doc);
virtual void add(dev::h256 const& _contractHash, std::string const& _doc) override;
/// Retrieves the natspec documentation as a string given a contract code hash
std::string retrieve(dev::h256 const& _contractHash) const override;
/// Given a json natspec string and the transaction data return the user notice
std::string getUserNotice(std::string const& json, const dev::bytes& _transactionData);
virtual std::string getUserNotice(std::string const& json, const dev::bytes& _transactionData) override;
/// Given a contract code hash and the transaction's data retrieve the natspec documention's
/// user notice for that transaction.
/// @returns The user notice or an empty string if no natspec for the contract exists
/// or if the existing natspec does not document the @c _methodName
std::string getUserNotice(dev::h256 const& _contractHash, dev::bytes const& _transactionDacta);
virtual std::string getUserNotice(dev::h256 const& _contractHash, dev::bytes const& _transactionDacta) override;
private:
ldb::ReadOptions m_readOptions;

2
alethzero/Transact.cpp

@ -360,7 +360,7 @@ void Transact::rejigData()
return;
}
else
gasNeeded = (qint64)min<bigint>(ethereum()->gasLimitRemaining(), ((b - value()) / gasPrice()));
gasNeeded = (qint64)min<bigint>(ethereum()->gasLimitRemaining(), ((b - value()) / max<u256>(gasPrice(), 1)));
// Dry-run execution to determine gas requirement and any execution errors
Address to;

195
eth/main.cpp

@ -84,15 +84,24 @@ void interactiveHelp()
<< " minestop Stops mining." << endl
<< " mineforce <enable> Forces mining, even when there are no transactions." << endl
<< " block Gives the current block height." << endl
<< " blockhashfromnumber <number> Gives the block hash with the givne number." << endl
<< " numberfromblockhash <hash> Gives the block number with the given hash." << endl
<< " blockqueue Gives the current block queue status." << endl
<< " findblock <hash> Searches for the block in the blockchain and blockqueue." << endl
<< " firstunknown Gives the first unknown block from the blockqueue." << endl
<< " retryunknown retries to import all unknown blocks from the blockqueue." << endl
<< " accounts Gives information on all owned accounts (balances, mining beneficiary and default signer)." << endl
<< " newaccount <name> Creates a new account with the given name." << endl
<< " transact Execute a given transaction." << endl
<< " txcreate Execute a given contract creation transaction." << endl
<< " send Execute a given transaction with current secret." << endl
<< " contract Create a new contract with current secret." << endl
<< " peers List the peers that are connected" << endl
#if ETH_FATDB || !ETH_TRUE
<< " listaccounts List the accounts on the network." << endl
<< " listcontracts List the contracts on the network." << endl
<< " balanceat <address> Gives the balance of the given account." << endl
<< " codeat <address> Gives the code of the given account." << endl
#endif
<< " setsigningkey <addr> Set the address with which to sign transactions." << endl
<< " setaddress <addr> Set the coinbase (mining payout) address." << endl
@ -125,6 +134,7 @@ void help()
<< " --session-sign-key <address> Sign all transactions with the key of the given address for this session only." << endl
<< " --master <password> Give the master password for the key store." << endl
<< " --password <password> Give a password for a private key." << endl
<< " --sentinel <server> Set the sentinel for reporting bad blocks or chain issues." << endl
<< endl
<< "Client transacting:" << endl
/*<< " -B,--block-fees <n> Set the block fee profit in the reference unit e.g. ¢ (default: 15)." << endl
@ -137,6 +147,7 @@ void help()
<< " -a,--address <addr> Set the coinbase (mining payout) address to addr (default: auto)." << endl
<< " -m,--mining <on/off/number> Enable mining, optionally for a specified number of blocks (default: off)" << endl
<< " -f,--force-mining Mine even when there are no transactions to mine (default: off)" << endl
<< " --mine-on-wrong-chain Mine even when we know it's the wrong chain (default: off)" << endl
<< " -C,--cpu When mining, use the CPU." << endl
<< " -G,--opencl When mining use the GPU via OpenCL." << endl
<< " --opencl-platform <n> When mining using -G/--opencl use OpenCL platform n (default: 0)." << endl
@ -278,6 +289,7 @@ int main(int argc, char** argv)
bool upnp = true;
WithExisting killChain = WithExisting::Trust;
bool jit = false;
string sentinel;
/// Networking params.
string clientName;
@ -293,6 +305,7 @@ int main(int argc, char** argv)
/// Mining params
unsigned mining = 0;
bool forceMining = false;
bool mineOnWrongChain = false;
Address signingKey;
Address sessionKey;
Address beneficiary = signingKey;
@ -375,6 +388,10 @@ int main(int argc, char** argv)
mode = OperationMode::Export;
filename = argv[++i];
}
else if (arg == "--sentinel" && i + 1 < argc)
sentinel = argv[++i];
else if (arg == "--mine-on-wrong-chain")
mineOnWrongChain = true;
else if (arg == "--format" && i + 1 < argc)
{
string m = argv[++i];
@ -670,6 +687,8 @@ int main(int argc, char** argv)
nodeMode == NodeMode::Full ? set<string>{"eth"/*, "shh"*/} : set<string>(),
netPrefs,
&nodesState);
web3.ethereum()->setMineOnBadChain(mineOnWrongChain);
web3.ethereum()->setSentinel(sentinel);
auto toNumber = [&](string const& s) -> unsigned {
if (s == "latest")
@ -961,9 +980,88 @@ int main(int argc, char** argv)
cout << "Current mining beneficiary:" << endl << beneficiary << endl;
cout << "Current signing account:" << endl << signingKey << endl;
}
else if (c && cmd == "blockhashfromnumber")
{
if (iss.peek() != -1)
{
unsigned number;
iss >> number;
cout << " hash of block: " << c->hashFromNumber(number).hex() << endl;
}
}
else if (c && cmd == "numberfromblockhash")
{
if (iss.peek() != -1)
{
string stringHash;
iss >> stringHash;
h256 hash = h256(fromHex(stringHash));
cout << " number of block: " << c->numberFromHash(hash) << endl;
}
}
else if (c && cmd == "block")
{
cout << "Current block: " <<c->blockChain().details().number << endl;
cout << "Current block: " << c->blockChain().details().number << endl;
}
else if (c && cmd == "blockqueue")
{
cout << "Current blockqueue status: " << endl << c->blockQueueStatus() << endl;
}
else if (c && cmd == "findblock")
{
if (iss.peek() != -1)
{
string stringHash;
iss >> stringHash;
h256 hash = h256(fromHex(stringHash));
// search in blockchain
cout << "search in blockchain... " << endl;
try
{
cout << c->blockInfo(hash) << endl;
}
catch(Exception& _e)
{
cout << "block not in blockchain" << endl;
cout << boost::diagnostic_information(_e) << endl;
}
cout << "search in blockqueue... " << endl;
switch(c->blockQueue().blockStatus(hash))
{
case QueueStatus::Ready:
cout << "Ready" << endl;
break;
case QueueStatus::Importing:
cout << "Importing" << endl;
break;
case QueueStatus::UnknownParent:
cout << "UnknownParent" << endl;
break;
case QueueStatus::Bad:
cout << "Bad" << endl;
break;
case QueueStatus::Unknown:
cout << "Unknown" << endl;
break;
default:
cout << "invalid queueStatus" << endl;
}
}
else
cwarn << "Require parameter: findblock HASH";
}
else if (c && cmd == "firstunknown")
{
cout << "first unknown blockhash: " << c->blockQueue().firstUnknown().hex() << endl;
}
else if (c && cmd == "retryunknown")
{
c->retryUnkonwn();
}
else if (cmd == "peers")
{
@ -1077,6 +1175,64 @@ int main(int argc, char** argv)
else
cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET DATA";
}
else if (c && cmd == "txcreate")
{
auto const& bc =c->blockChain();
auto h = bc.currentHash();
auto blockData = bc.block(h);
BlockInfo info(blockData);
if (iss.peek() != -1)
{
u256 amount;
u256 gasPrice;
u256 gas;
string sechex;
string sdata;
iss >> amount >> gasPrice >> gas >> sechex >> sdata;
if (!gasPrice)
gasPrice = gasPricer->bid(priority);
cnote << "Data:";
cnote << sdata;
bytes data = dev::eth::parseData(sdata);
cnote << "Bytes:";
string sbd = asString(data);
bytes bbd = asBytes(sbd);
stringstream ssbd;
ssbd << bbd;
cnote << ssbd.str();
int ssize = sechex.length();
u256 minGas = (u256)Transaction::gasRequired(data, 0);
if (gas < minGas)
cwarn << "Minimum gas amount is" << minGas;
else if (ssize < 40)
{
if (ssize > 0)
cwarn << "Invalid secret length:" << ssize;
}
else
{
try
{
Secret secret = h256(fromHex(sechex));
cout << " new contract address : " << c->submitTransaction(secret, amount, data, gas, gasPrice) << endl;
}
catch (BadHexCharacter& _e)
{
cwarn << "invalid hex character, transaction rejected";
cwarn << boost::diagnostic_information(_e);
}
catch (...)
{
cwarn << "transaction rejected";
}
}
}
else
cwarn << "Require parameters: submitTransaction ADDRESS AMOUNT GASPRICE GAS SECRET INIT";
}
#if ETH_FATDB
else if (c && cmd == "listcontracts")
{
@ -1100,6 +1256,43 @@ int main(int argc, char** argv)
cout << ss << endl;
}
}
else if (c && cmd == "balanceat")
{
if (iss.peek() != -1)
{
string stringHash;
iss >> stringHash;
Address address = h160(fromHex(stringHash));
cout << "balance of " << stringHash << " is: " << toString(c->balanceAt(address)) << endl;
}
}
// TODO implement << operator for std::unorderd_map
// else if (c && cmd == "storageat")
// {
// if (iss.peek() != -1)
// {
// string stringHash;
// iss >> stringHash;
// Address address = h160(fromHex(stringHash));
// cout << "storage at " << stringHash << " is: " << c->storageAt(address) << endl;
// }
// }
else if (c && cmd == "codeat")
{
if (iss.peek() != -1)
{
string stringHash;
iss >> stringHash;
Address address = h160(fromHex(stringHash));
cout << "code at " << stringHash << " is: " << toHex(c->codeAt(address)) << endl;
}
}
#endif
else if (c && cmd == "send")
{

39
ethkey/KeyAux.h

@ -102,6 +102,7 @@ public:
List,
New,
Import,
ImportWithAddress,
Export,
Recode,
Kill
@ -159,6 +160,13 @@ public:
m_inputs = strings(1, argv[++i]);
m_name = argv[++i];
}
else if ((arg == "-i" || arg == "--import-with-address") && i + 3 < argc)
{
m_mode = OperationMode::ImportWithAddress;
m_inputs = strings(1, argv[++i]);
m_address = Address(argv[++i]);
m_name = argv[++i];
}
else if (arg == "--export")
m_mode = OperationMode::Export;
else if (arg == "--recode")
@ -314,6 +322,33 @@ public:
cout << " ICAP: " << ICAP(k.address()).encoded() << endl;
break;
}
case OperationMode::ImportWithAddress:
{
string const& i = m_inputs[0];
h128 u;
bytes b;
b = fromHex(i);
if (b.size() != 32)
{
std::string s = contentsString(i);
b = fromHex(s);
if (b.size() != 32)
u = wallet.store().importKey(i);
}
if (!u && b.size() == 32)
u = wallet.store().importSecret(b, lockPassword(toAddress(Secret(b)).abridged()));
if (!u)
{
cerr << "Cannot import " << i << " not a file or secret." << endl;
break;
}
wallet.importExisting(u, m_name, m_address);
cout << "Successfully imported " << i << ":" << endl;
cout << " Name: " << m_name << endl;
cout << " Address: " << m_address << endl;
cout << " UUID: " << toUUID(u) << endl;
break;
}
case OperationMode::List:
{
vector<u128> bare;
@ -369,6 +404,7 @@ public:
<< " -l,--list List all keys available in wallet." << endl
<< " -n,--new <name> Create a new key with given name and add it in the wallet." << endl
<< " -i,--import [<uuid>|<file>|<secret-hex>] <name> Import keys from given source and place in wallet." << endl
<< " --import-with-address [<uuid>|<file>|<secret-hex>] <address> <name> Import keys from given source with given address and place in wallet." << endl
<< " -e,--export [ <address>|<uuid> , ... ] Export given keys." << endl
<< " -r,--recode [ <address>|<uuid>|<file> , ... ] Decrypt and re-encrypt given keys." << endl
<< "Wallet configuration:" << endl
@ -418,8 +454,9 @@ private:
string m_lockHint;
bool m_icap = true;
/// Creating
/// Creating/importing
string m_name;
Address m_address;
/// Importing
strings m_inputs;

7
ethminer/CMakeLists.txt

@ -5,7 +5,10 @@ aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..)
include_directories(${Boost_INCLUDE_DIRS})
if (JSONRPC)
include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
endif()
set(EXECUTABLE ethminer)
@ -19,10 +22,6 @@ target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES})
if (JSONRPC)
target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_CLIENT_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${CURL_LIBRARIES})
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
eth_copy_dlls(${EXECUTABLE} CURL_DLLS)
endif()
endif()
target_link_libraries(${EXECUTABLE} ethcore)

7
ethminer/MinerAux.h

@ -127,6 +127,11 @@ public:
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
}
else if (arg == "--list-devices")
{
ProofOfWork::GPUMiner::listDevices();
exit(0);
}
else if (arg == "--use-chunks")
{
dagChunks = 4;
@ -175,7 +180,7 @@ public:
m_minerType = MinerType::CPU;
else if (arg == "-G" || arg == "--opencl")
{
if (!ProofOfWork::GPUMiner::haveSufficientGPUMemory())
if (!ProofOfWork::GPUMiner::haveSufficientMemory())
{
cout << "No GPU device with sufficient memory was found. Defaulting to CPU" << endl;
m_minerType = MinerType::CPU;

5
json_spirit/json_spirit_writer_template.h

@ -25,13 +25,9 @@ namespace json_spirit
return 'A' - 10 + ch;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs")
template< class String_type >
String_type non_printable_to_string( unsigned int c )
{
typedef typename String_type::value_type Char_type;
String_type result( 6, '\\' );
result[1] = 'u';
@ -43,7 +39,6 @@ namespace json_spirit
return result;
}
#pragma GCC diagnostic pop
template< typename Char_type, class String_type >
bool add_esc_char( Char_type c, String_type& s )

2
libdevcore/Common.cpp

@ -28,7 +28,7 @@ using namespace dev;
namespace dev
{
char const* Version = "0.9.23";
char const* Version = "0.9.24";
const u256 UndefinedU256 = ~(u256)0;

52
libdevcore/CommonData.cpp

@ -67,7 +67,7 @@ std::string dev::randomWord()
return ret;
}
int dev::fromHex(char _i)
int dev::fromHex(char _i, WhenError _throw)
{
if (_i >= '0' && _i <= '9')
return _i - '0';
@ -75,7 +75,10 @@ int dev::fromHex(char _i)
return _i - 'a' + 10;
if (_i >= 'A' && _i <= 'F')
return _i - 'A' + 10;
BOOST_THROW_EXCEPTION(BadHexCharacter() << errinfo_invalidSymbol(_i));
if (_throw == WhenError::Throw)
BOOST_THROW_EXCEPTION(BadHexCharacter() << errinfo_invalidSymbol(_i));
else
return -1;
}
bytes dev::fromHex(std::string const& _s, WhenError _throw)
@ -85,33 +88,26 @@ bytes dev::fromHex(std::string const& _s, WhenError _throw)
ret.reserve((_s.size() - s + 1) / 2);
if (_s.size() % 2)
try
{
ret.push_back(fromHex(_s[s++]));
}
catch (...)
{
ret.push_back(0);
// msvc does not support it
#ifndef BOOST_NO_EXCEPTIONS
cwarn << boost::current_exception_diagnostic_information();
#endif
if (_throw == WhenError::Throw)
throw;
}
{
int h = fromHex(_s[s++], WhenError::DontThrow);
if (h != -1)
ret.push_back(h);
else if (_throw == WhenError::Throw)
throw BadHexCharacter();
else
return bytes();
}
for (unsigned i = s; i < _s.size(); i += 2)
try
{
ret.push_back((byte)(fromHex(_s[i]) * 16 + fromHex(_s[i + 1])));
}
catch (...){
ret.push_back(0);
#ifndef BOOST_NO_EXCEPTIONS
cwarn << boost::current_exception_diagnostic_information();
#endif
if (_throw == WhenError::Throw)
throw;
}
{
int h = fromHex(_s[i], WhenError::DontThrow);
int l = fromHex(_s[i + 1], WhenError::DontThrow);
if (h != -1 && l != -1)
ret.push_back((byte)(h * 16 + l));
else if (_throw == WhenError::Throw)
throw BadHexCharacter();
else
return bytes();
}
return ret;
}

2
libdevcore/CommonData.h

@ -61,7 +61,7 @@ std::string toHex(_T const& _data, int _w = 2, HexPrefix _prefix = HexPrefix::Do
/// Converts a (printable) ASCII hex character into the correspnding integer value.
/// @example fromHex('A') == 10 && fromHex('f') == 15 && fromHex('5') == 5
int fromHex(char _i);
int fromHex(char _i, WhenError _throw);
/// Converts a (printable) ASCII hex string into the corresponding byte stream.
/// @example fromHex("41626261") == asBytes("Abba")

39
libdevcore/Exceptions.h

@ -30,7 +30,8 @@
namespace dev
{
// base class for all exceptions
/// Base class for all exceptions.
struct Exception: virtual std::exception, virtual boost::exception
{
Exception(std::string _message = std::string()): m_message(std::move(_message)) {}
@ -40,20 +41,26 @@ private:
std::string m_message;
};
struct BadHexCharacter: virtual Exception {};
struct RLPException: virtual Exception {};
struct BadCast: virtual RLPException {};
struct BadRLP: virtual RLPException {};
struct OversizeRLP: virtual RLPException {};
struct UndersizeRLP: virtual RLPException {};
struct NoNetworking: virtual Exception {};
struct NoUPnPDevice: virtual Exception {};
struct RootNotFound: virtual Exception {};
struct BadRoot: virtual Exception {};
struct FileError: virtual Exception {};
struct Overflow: virtual Exception {};
#define DEV_SIMPLE_EXCEPTION(X) struct X: virtual Exception { public: X(): Exception(#X) {} }
/// Base class for all RLP exceptions.
struct RLPException: virtual Exception { RLPException(std::string _message = std::string()): Exception(_message) {} };
#define DEV_SIMPLE_EXCEPTION_RLP(X) struct X: virtual RLPException { public: X(): RLPException(#X) {} }
DEV_SIMPLE_EXCEPTION_RLP(BadCast);
DEV_SIMPLE_EXCEPTION_RLP(BadRLP);
DEV_SIMPLE_EXCEPTION_RLP(OversizeRLP);
DEV_SIMPLE_EXCEPTION_RLP(UndersizeRLP);
DEV_SIMPLE_EXCEPTION(BadHexCharacter);
DEV_SIMPLE_EXCEPTION(NoNetworking);
DEV_SIMPLE_EXCEPTION(NoUPnPDevice);
DEV_SIMPLE_EXCEPTION(RootNotFound);
DEV_SIMPLE_EXCEPTION(BadRoot);
DEV_SIMPLE_EXCEPTION(FileError);
DEV_SIMPLE_EXCEPTION(Overflow);
DEV_SIMPLE_EXCEPTION(FailedInvariant);
struct InterfaceNotSupported: virtual Exception { public: InterfaceNotSupported(std::string _f): Exception("Interface " + _f + " not supported.") {} };
struct FailedInvariant: virtual Exception {};
struct ExternalFunctionFailure: virtual Exception { public: ExternalFunctionFailure(std::string _f): Exception("Function " + _f + "() failed.") {} };
// error information to be added to exceptions
@ -66,5 +73,7 @@ using errinfo_min = boost::error_info<struct tag_min, bigint>;
using errinfo_max = boost::error_info<struct tag_max, bigint>;
using RequirementError = boost::tuple<errinfo_required, errinfo_got>;
using errinfo_hash256 = boost::error_info<struct tag_hash, h256>;
using HashMismatchError = boost::tuple<errinfo_hash256, errinfo_hash256>;
using errinfo_required_h256 = boost::error_info<struct tag_required_h256, h256>;
using errinfo_got_h256 = boost::error_info<struct tag_get_h256, h256>;
using Hash256RequirementError = boost::tuple<errinfo_required_h256, errinfo_got_h256>;
}

2
libdevcore/FixedHash.h

@ -113,7 +113,7 @@ public:
/// @returns an abridged version of the hash as a user-readable hex string.
std::string abridged() const { return toHex(ref().cropped(0, 4)) + "\342\200\246"; }
/// @returns an abridged version of the hash as a user-readable hex string.
/// @returns the hash as a user-readable hex string.
std::string hex() const { return toHex(ref()); }
/// @returns a mutable byte vector_ref to the object's data.

8
libdevcore/Log.cpp

@ -40,6 +40,14 @@ mutex x_logOverride;
/// or equal to the currently output verbosity (g_logVerbosity).
static map<type_info const*, bool> s_logOverride;
bool isLogVisible(std::type_info const* _ch, bool _default)
{
Guard l(x_logOverride);
if (s_logOverride.count(_ch))
return s_logOverride[_ch];
return _default;
}
LogOverrideAux::LogOverrideAux(std::type_info const* _ch, bool _value):
m_ch(_ch)
{

3
libdevcore/Log.h

@ -73,6 +73,9 @@ public:
LogOverride(bool _value): LogOverrideAux(&typeid(Channel), _value) {}
};
bool isChannelVisible(std::type_info const* _ch, bool _default);
template <class Channel> bool isChannelVisible() { return isChannelVisible(&typeid(Channel), Channel::verbosity <= g_logVerbosity); }
/// Temporary changes system's verbosity for specific function. Restores the old verbosity when function returns.
/// Not thread-safe, use with caution!
struct VerbosityHolder

8
libdevcore/RangeMask.h

@ -219,6 +219,14 @@ public:
return uit == m_ranges.end() ? m_all.second : uit->first;
}
size_t size() const
{
size_t c = 0;
for (auto const& r: this->m_ranges)
c += r.second - r.first;
return c;
}
private:
UnsignedRange m_all;
std::map<T, T> m_ranges;

4
libdevcrypto/Common.cpp

@ -54,7 +54,7 @@ Public dev::toPublic(Secret const& _secret)
{
Public p;
s_secp256k1.toPublic(_secret, p);
return std::move(p);
return p;
}
Address dev::toAddress(Public const& _public)
@ -230,7 +230,7 @@ h256 crypto::kdf(Secret const& _priv, h256 const& _hash)
if (!s || !_hash || !_priv)
BOOST_THROW_EXCEPTION(InvalidState());
return std::move(s);
return s;
}
h256 Nonce::get(bool _commit)

2
libdevcrypto/CryptoPP.cpp

@ -61,7 +61,7 @@ bytes Secp256k1::eciesKDF(Secret _z, bytes _s1, unsigned kdByteLen)
}
k.resize(kdByteLen);
return move(k);
return k;
}
void Secp256k1::encryptECIES(Public const& _k, bytes& io_cipher)

2
libdevcrypto/CryptoPP.h

@ -59,7 +59,7 @@ namespace crypto
using namespace CryptoPP;
inline ECP::Point publicToPoint(Public const& _p) { Integer x(_p.data(), 32); Integer y(_p.data() + 32, 32); return std::move(ECP::Point(x,y)); }
inline ECP::Point publicToPoint(Public const& _p) { Integer x(_p.data(), 32); Integer y(_p.data() + 32, 32); return ECP::Point(x,y); }
inline Integer secretToExponent(Secret const& _s) { return std::move(Integer(_s.data(), Secret::size)); }

4
libdevcrypto/OverlayDB.cpp

@ -95,7 +95,7 @@ bytes OverlayDB::lookupAux(h256 const& _h) const
{
bytes ret = MemoryDB::lookupAux(_h);
if (!ret.empty() || !m_db)
return move(ret);
return ret;
std::string v;
bytes b = _h.asBytes();
b.push_back(255); // for aux
@ -116,7 +116,7 @@ std::string OverlayDB::lookup(h256 const& _h) const
std::string ret = MemoryDB::lookup(_h);
if (ret.empty() && m_db)
m_db->Get(m_readOptions, ldb::Slice((char const*)_h.data(), 32), &ret);
return move(ret);
return ret;
}
bool OverlayDB::exists(h256 const& _h) const

2
libdevcrypto/SecretStore.cpp

@ -164,7 +164,7 @@ void SecretStore::load(std::string const& _keysPath)
h128 SecretStore::readKey(std::string const& _file, bool _deleteFile)
{
cdebug << "Reading" << _file;
cnote << "Reading" << _file;
return readKeyContent(contentsString(_file), _deleteFile ? _file : string());
}

51
libethash-cl/ethash_cl_miner.cpp

@ -127,7 +127,7 @@ unsigned ethash_cl_miner::get_num_devices(unsigned _platformId)
return devices.size();
}
bool ethash_cl_miner::haveSufficientGPUMemory(unsigned _platformId)
bool ethash_cl_miner::haveSufficientGPUMemory()
{
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
@ -136,15 +136,25 @@ bool ethash_cl_miner::haveSufficientGPUMemory(unsigned _platformId)
ETHCL_LOG("No OpenCL platforms found.");
return false;
}
for (unsigned i = 0; i < platforms.size(); ++i)
if (haveSufficientGPUMemory(i))
return true;
return false;
}
bool ethash_cl_miner::haveSufficientGPUMemory(unsigned _platformId)
{
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
if (_platformId >= platforms.size())
return false;
std::vector<cl::Device> devices;
unsigned platform_num = std::min<unsigned>(_platformId, platforms.size() - 1);
platforms[platform_num].getDevices(CL_DEVICE_TYPE_ALL, &devices);
if (devices.empty())
{
ETHCL_LOG("No OpenCL devices found.");
return false;
}
for (cl::Device const& device: devices)
{
@ -168,6 +178,39 @@ bool ethash_cl_miner::haveSufficientGPUMemory(unsigned _platformId)
return false;
}
void ethash_cl_miner::listDevices()
{
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
if (platforms.empty())
{
ETHCL_LOG("No OpenCL platforms found.");
return;
}
for (unsigned i = 0; i < platforms.size(); ++i)
listDevices(i);
}
void ethash_cl_miner::listDevices(unsigned _platformId)
{
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
if (_platformId >= platforms.size())
return;
std::string outString ="Listing OpenCL devices for platform " + to_string(_platformId) + "\n[deviceID] deviceName\n";
std::vector<cl::Device> devices;
platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices);
unsigned i = 0;
std::string deviceString;
for (cl::Device const& device: devices)
{
outString += "[" + to_string(i) + "] " + device.getInfo<CL_DEVICE_NAME>() + "\n";
++i;
}
ETHCL_LOG(outString);
}
void ethash_cl_miner::finish()
{
if (m_queue())

5
libethash-cl/ethash_cl_miner.h

@ -35,7 +35,10 @@ public:
static unsigned get_num_platforms();
static unsigned get_num_devices(unsigned _platformId = 0);
static std::string platform_info(unsigned _platformId = 0, unsigned _deviceId = 0);
static bool haveSufficientGPUMemory(unsigned _platformId = 0);
static bool haveSufficientGPUMemory();
static bool haveSufficientGPUMemory(unsigned _platformId);
static void listDevices();
static void listDevices(unsigned _platformId);
bool init(
uint8_t const* _dag,

24
libethcore/BlockInfo.cpp

@ -139,7 +139,6 @@ void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s, h256 const
mixHash = _header[field = 13].toHash<h256>(RLP::VeryStrict);
nonce = _header[field = 14].toHash<Nonce>(RLP::VeryStrict);
}
catch (Exception const& _e)
{
_e << errinfo_name("invalid block header format") << BadFieldError(field, toHex(_header[field].data().toBytes()));
@ -151,9 +150,26 @@ void BlockInfo::populateFromHeader(RLP const& _header, Strictness _s, h256 const
// check it hashes according to proof of work or that it's the genesis block.
if (_s == CheckEverything && parentHash && !ProofOfWork::verify(*this))
BOOST_THROW_EXCEPTION(InvalidBlockNonce() << errinfo_hash256(headerHash(WithoutNonce)) << errinfo_nonce(nonce) << errinfo_difficulty(difficulty));
{
InvalidBlockNonce ex;
ex << errinfo_hash256(headerHash(WithoutNonce));
ex << errinfo_nonce(nonce);
ex << errinfo_difficulty(difficulty);
ex << errinfo_seedHash(seedHash());
ex << errinfo_target(boundary());
ex << errinfo_mixHash(mixHash);
Ethash::Result er = EthashAux::eval(seedHash(), headerHash(WithoutNonce), nonce);
ex << errinfo_ethashResult(make_tuple(er.value, er.mixHash));
BOOST_THROW_EXCEPTION(ex);
}
else if (_s == QuickNonce && parentHash && !ProofOfWork::preVerify(*this))
BOOST_THROW_EXCEPTION(InvalidBlockNonce() << errinfo_hash256(headerHash(WithoutNonce)) << errinfo_nonce(nonce) << errinfo_difficulty(difficulty));
{
InvalidBlockNonce ex;
ex << errinfo_hash256(headerHash(WithoutNonce));
ex << errinfo_nonce(nonce);
ex << errinfo_difficulty(difficulty);
BOOST_THROW_EXCEPTION(ex);
}
if (_s != CheckNothing)
{
@ -224,7 +240,7 @@ void BlockInfo::verifyInternals(bytesConstRef _block) const
for (auto const& t: txs)
cdebug << toHex(t);
BOOST_THROW_EXCEPTION(InvalidTransactionsHash() << HashMismatchError(expectedRoot, transactionsRoot));
BOOST_THROW_EXCEPTION(InvalidTransactionsRoot() << Hash256RequirementError(expectedRoot, transactionsRoot));
}
clog(BlockInfoDiagnosticsChannel) << "Expected uncle hash:" << toString(sha3(root[2].data()));
if (sha3Uncles != sha3(root[2].data()))

15
libethcore/Ethash.cpp

@ -364,11 +364,6 @@ void Ethash::GPUMiner::pause()
stopWorking();
}
bool Ethash::GPUMiner::haveSufficientGPUMemory()
{
return ethash_cl_miner::haveSufficientGPUMemory(s_platformId);
}
std::string Ethash::GPUMiner::platformInfo()
{
return ethash_cl_miner::platform_info(s_platformId, s_deviceId);
@ -379,6 +374,16 @@ unsigned Ethash::GPUMiner::getNumDevices()
return ethash_cl_miner::get_num_devices(s_platformId);
}
void Ethash::GPUMiner::listDevices()
{
return ethash_cl_miner::listDevices();
}
bool Ethash::GPUMiner::haveSufficientMemory()
{
return ethash_cl_miner::haveSufficientGPUMemory();
}
#endif
}

6
libethcore/Ethash.h

@ -87,10 +87,11 @@ public:
static unsigned instances() { return s_numInstances > 0 ? s_numInstances : std::thread::hardware_concurrency(); }
static std::string platformInfo();
static bool haveSufficientGPUMemory() { return false; }
static void setDefaultPlatform(unsigned) {}
static void setDagChunks(unsigned) {}
static void setDefaultDevice(unsigned) {}
static void listDevices() {}
static bool haveSufficientMemory() { return false; }
static void setNumInstances(unsigned _instances) { s_numInstances = std::min<unsigned>(_instances, std::thread::hardware_concurrency()); }
protected:
void kickOff() override
@ -117,8 +118,9 @@ public:
static unsigned instances() { return s_numInstances > 0 ? s_numInstances : 1; }
static std::string platformInfo();
static bool haveSufficientGPUMemory();
static unsigned getNumDevices();
static void listDevices();
static bool haveSufficientMemory();
static void setDefaultPlatform(unsigned _id) { s_platformId = _id; }
static void setDefaultDevice(unsigned _id) { s_deviceId = _id; }
static void setNumInstances(unsigned _instances) { s_numInstances = std::min<unsigned>(_instances, getNumDevices()); }

77
libethcore/Exceptions.h

@ -35,46 +35,45 @@ using errinfo_field = boost::error_info<struct tag_field, int>;
using errinfo_data = boost::error_info<struct tag_data, std::string>;
using errinfo_nonce = boost::error_info<struct tag_nonce, h64>;
using errinfo_difficulty = boost::error_info<struct tag_difficulty, u256>;
using errinfo_target = boost::error_info<struct tag_target, h256>;
using errinfo_seedHash = boost::error_info<struct tag_seedHash, h256>;
using errinfo_mixHash = boost::error_info<struct tag_mixHash, h256>;
using errinfo_ethashResult = boost::error_info<struct tag_ethashResult, std::tuple<h256, h256>>;
using BadFieldError = boost::tuple<errinfo_field, errinfo_data>;
struct DatabaseAlreadyOpen: virtual dev::Exception {};
struct OutOfGasBase: virtual dev::Exception {};
struct NotEnoughAvailableSpace: virtual dev::Exception {};
struct NotEnoughCash: virtual dev::Exception {};
struct GasPriceTooLow: virtual dev::Exception {};
struct BlockGasLimitReached: virtual dev::Exception {};
struct NoSuchContract: virtual dev::Exception {};
struct ContractAddressCollision: virtual dev::Exception {};
struct FeeTooSmall: virtual dev::Exception {};
struct TooMuchGasUsed: virtual dev::Exception {};
struct ExtraDataTooBig: virtual dev::Exception {};
struct InvalidSignature: virtual dev::Exception {};
struct InvalidBlockFormat: virtual dev::Exception {};
struct InvalidUnclesHash: virtual dev::Exception {};
struct InvalidUncle: virtual dev::Exception {};
struct TooManyUncles: virtual dev::Exception {};
struct UncleTooOld: virtual dev::Exception {};
struct UncleIsBrother: virtual dev::Exception {};
struct UncleInChain: virtual dev::Exception {};
struct DuplicateUncleNonce: virtual dev::Exception {};
struct InvalidStateRoot: virtual dev::Exception {};
struct InvalidGasUsed: virtual dev::Exception {};
struct InvalidTransactionsHash: virtual dev::Exception {};
struct InvalidTransaction: virtual dev::Exception {};
struct InvalidDifficulty: virtual dev::Exception {};
struct InvalidGasLimit: virtual dev::Exception {};
struct InvalidTransactionGasUsed: virtual dev::Exception {};
struct InvalidTransactionsStateRoot: virtual dev::Exception {};
struct InvalidReceiptsStateRoot: virtual dev::Exception {};
struct InvalidTimestamp: virtual dev::Exception {};
struct InvalidLogBloom: virtual dev::Exception {};
struct InvalidNonce: virtual dev::Exception {};
struct InvalidBlockHeaderItemCount: virtual dev::Exception {};
struct InvalidBlockNonce: virtual dev::Exception {};
struct InvalidParentHash: virtual dev::Exception {};
struct InvalidNumber: virtual dev::Exception {};
struct InvalidContractAddress: virtual public dev::Exception {};
struct DAGCreationFailure: virtual public dev::Exception {};
struct DAGComputeFailure: virtual public dev::Exception {};
DEV_SIMPLE_EXCEPTION(OutOfGasBase);
DEV_SIMPLE_EXCEPTION(OutOfGasIntrinsic);
DEV_SIMPLE_EXCEPTION(NotEnoughAvailableSpace);
DEV_SIMPLE_EXCEPTION(NotEnoughCash);
DEV_SIMPLE_EXCEPTION(GasPriceTooLow);
DEV_SIMPLE_EXCEPTION(BlockGasLimitReached);
DEV_SIMPLE_EXCEPTION(FeeTooSmall);
DEV_SIMPLE_EXCEPTION(TooMuchGasUsed);
DEV_SIMPLE_EXCEPTION(ExtraDataTooBig);
DEV_SIMPLE_EXCEPTION(InvalidSignature);
DEV_SIMPLE_EXCEPTION(InvalidBlockFormat);
DEV_SIMPLE_EXCEPTION(InvalidUnclesHash);
DEV_SIMPLE_EXCEPTION(TooManyUncles);
DEV_SIMPLE_EXCEPTION(UncleTooOld);
DEV_SIMPLE_EXCEPTION(UncleIsBrother);
DEV_SIMPLE_EXCEPTION(UncleInChain);
DEV_SIMPLE_EXCEPTION(InvalidStateRoot);
DEV_SIMPLE_EXCEPTION(InvalidGasUsed);
DEV_SIMPLE_EXCEPTION(InvalidTransactionsRoot);
DEV_SIMPLE_EXCEPTION(InvalidDifficulty);
DEV_SIMPLE_EXCEPTION(InvalidGasLimit);
DEV_SIMPLE_EXCEPTION(InvalidReceiptsStateRoot);
DEV_SIMPLE_EXCEPTION(InvalidTimestamp);
DEV_SIMPLE_EXCEPTION(InvalidLogBloom);
DEV_SIMPLE_EXCEPTION(InvalidNonce);
DEV_SIMPLE_EXCEPTION(InvalidBlockHeaderItemCount);
DEV_SIMPLE_EXCEPTION(InvalidBlockNonce);
DEV_SIMPLE_EXCEPTION(InvalidParentHash);
DEV_SIMPLE_EXCEPTION(InvalidNumber);
DEV_SIMPLE_EXCEPTION(DatabaseAlreadyOpen);
DEV_SIMPLE_EXCEPTION(DAGCreationFailure);
DEV_SIMPLE_EXCEPTION(DAGComputeFailure);
}
}

23
libethcore/KeyManager.cpp

@ -89,18 +89,18 @@ bool KeyManager::load(std::string const& _pass)
for (auto const& i: s[1])
{
m_keyInfo[m_addrLookup[(Address)i[0]] = (h128)i[1]] = KeyInfo((h256)i[2], (std::string)i[3]);
cdebug << toString((Address)i[0]) << toString((h128)i[1]) << toString((h256)i[2]) << (std::string)i[3];
// cdebug << toString((Address)i[0]) << toString((h128)i[1]) << toString((h256)i[2]) << (std::string)i[3];
}
for (auto const& i: s[2])
m_passwordInfo[(h256)i[0]] = (std::string)i[1];
m_password = (string)s[3];
}
cdebug << hashPassword(m_password) << toHex(m_password);
// cdebug << hashPassword(m_password) << toHex(m_password);
m_cachedPasswords[hashPassword(m_password)] = m_password;
cdebug << hashPassword(asString(m_key.ref())) << m_key.hex();
// cdebug << hashPassword(asString(m_key.ref())) << m_key.hex();
m_cachedPasswords[hashPassword(asString(m_key.ref()))] = asString(m_key.ref());
cdebug << hashPassword(_pass) << _pass;
// cdebug << hashPassword(_pass) << _pass;
m_cachedPasswords[m_master = hashPassword(_pass)] = _pass;
return true;
}
@ -141,7 +141,7 @@ std::string KeyManager::getPassword(h256 const& _passHash, function<std::string(
std::string p = _pass();
if (p.empty())
break;
if (hashPassword(p) == _passHash || !_passHash)
if (hashPassword(p) == _passHash || _passHash == UnknownPassword)
{
m_cachedPasswords[hashPassword(p)] = p;
return p;
@ -186,12 +186,17 @@ void KeyManager::importExisting(h128 const& _uuid, std::string const& _info, std
return;
Address a = KeyPair(Secret(key)).address();
auto passHash = hashPassword(_pass);
if (!m_passwordInfo.count(passHash))
m_passwordInfo[passHash] = _passInfo;
if (!m_cachedPasswords.count(passHash))
m_cachedPasswords[passHash] = _pass;
m_addrLookup[a] = _uuid;
m_keyInfo[_uuid].passHash = passHash;
importExisting(_uuid, _info, a, passHash, _passInfo);
}
void KeyManager::importExisting(h128 const& _uuid, std::string const& _info, Address const& _address, h256 const& _passHash, std::string const& _passInfo)
{
if (!m_passwordInfo.count(_passHash))
m_passwordInfo[_passHash] = _passInfo;
m_addrLookup[_address] = _uuid;
m_keyInfo[_uuid].passHash = _passHash;
m_keyInfo[_uuid].info = _info;
write(m_keysFile);
}

11
libethcore/KeyManager.h

@ -30,17 +30,19 @@ namespace dev
{
namespace eth
{
class UnknownPassword: public Exception {};
class PasswordUnknown: public Exception {};
struct KeyInfo
{
KeyInfo() = default;
KeyInfo(h256 const& _passHash, std::string const& _info): passHash(_passHash), info(_info) {}
h256 passHash;
std::string info;
h256 passHash; ///< Hash of the password or h256() if unknown.
std::string info; ///< Name of the key, or JSON key info if begins with '{'.
};
static const auto DontKnowThrow = [](){ throw UnknownPassword(); return std::string(); };
static const h256 UnknownPassword;
static const auto DontKnowThrow = [](){ throw PasswordUnknown(); return std::string(); };
enum class SemanticPassword
{
@ -89,6 +91,7 @@ public:
SecretStore& store() { return m_store; }
void importExisting(h128 const& _uuid, std::string const& _info, std::string const& _pass, std::string const& _passInfo);
void importExisting(h128 const& _uuid, std::string const& _info) { importExisting(_uuid, _info, defaultPassword(), std::string()); }
void importExisting(h128 const& _uuid, std::string const& _info, Address const& _addr, h256 const& _passHash = h256(), std::string const& _passInfo = std::string());
Secret secret(Address const& _address, std::function<std::string()> const& _pass = DontKnowThrow) const;
Secret secret(h128 const& _uuid, std::function<std::string()> const& _pass = DontKnowThrow) const;

48
libethereum/BlockChain.cpp

@ -331,9 +331,18 @@ tuple<h256s, h256s, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st
// Can't continue - chain bad.
badBlocks.push_back(block.first.hash());
}
catch (Exception const& _e)
catch (dev::eth::FutureTime)
{
cnote << "Exception while importing block. Someone (Jeff? That you?) seems to be giving us dodgy blocks!" << LogTag::Error << diagnostic_information(_e);
cwarn << "ODD: Import queue contains a block with future time." << LogTag::Error << boost::current_exception_diagnostic_information();
// NOTE: don't reimport since the queue should guarantee everything in the past.
// Can't continue - chain bad.
badBlocks.push_back(block.first.hash());
}
catch (Exception& ex)
{
cnote << "Exception while importing block. Someone (Jeff? That you?) seems to be giving us dodgy blocks!" << LogTag::Error << diagnostic_information(ex);
if (m_onBad)
m_onBad(ex);
// NOTE: don't reimport since the queue should guarantee everything in the right order.
// Can't continue - chain bad.
badBlocks.push_back(block.first.hash());
@ -360,8 +369,10 @@ pair<ImportResult, ImportRoute> BlockChain::attemptImport(bytes const& _block, O
{
return make_pair(ImportResult::FutureTime, make_pair(h256s(), h256s()));
}
catch (...)
catch (Exception& ex)
{
if (m_onBad)
m_onBad(ex);
return make_pair(ImportResult::Malformed, make_pair(h256s(), h256s()));
}
}
@ -379,10 +390,11 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
bi.verifyInternals(&_block);
}
#if ETH_CATCH
catch (Exception const& _e)
catch (Exception& ex)
{
clog(BlockChainNote) << " Malformed block: " << diagnostic_information(_e);
_e << errinfo_comment("Malformed block ");
clog(BlockChainNote) << " Malformed block: " << diagnostic_information(ex);
ex << errinfo_now(time(0));
ex << errinfo_block(_block);
throw;
}
#endif
@ -470,14 +482,8 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
blb.blooms.push_back(s.receipt(i).bloom());
br.receipts.push_back(s.receipt(i));
}
try {
s.cleanup(true);
}
catch (BadRoot)
{
cwarn << "BadRoot error. Retrying import later.";
BOOST_THROW_EXCEPTION(FutureTime());
}
s.cleanup(true);
td = pd.totalDifficulty + tdIncrease;
@ -520,20 +526,20 @@ ImportRoute BlockChain::import(BlockInfo const& _bi, bytes const& _block, Overla
#endif
}
#if ETH_CATCH
catch (InvalidNonce const& _e)
catch (BadRoot& ex)
{
clog(BlockChainNote) << " Malformed block: " << diagnostic_information(_e);
_e << errinfo_comment("Malformed block ");
throw;
cwarn << "BadRoot error. Retrying import later.";
BOOST_THROW_EXCEPTION(FutureTime());
}
catch (Exception const& _e)
catch (Exception& ex)
{
clog(BlockChainWarn) << " Malformed block: " << diagnostic_information(_e);
_e << errinfo_comment("Malformed block ");
clog(BlockChainWarn) << " Malformed block: " << diagnostic_information(ex);
clog(BlockChainWarn) << "Block: " << _bi.hash();
clog(BlockChainWarn) << _bi;
clog(BlockChainWarn) << "Block parent: " << _bi.parentHash;
clog(BlockChainWarn) << BlockInfo(block(_bi.parentHash));
ex << errinfo_now(time(0));
ex << errinfo_block(_block);
throw;
}
#endif

5
libethereum/BlockChain.h

@ -256,6 +256,9 @@ public:
/// Deallocate unused data.
void garbageCollect(bool _force = false);
/// Change the function that is called with a bad block.
template <class T> void setOnBad(T const& _t) { m_onBad = _t; }
private:
static h256 chunkId(unsigned _level, unsigned _index) { return h256(_index * 0xff + _level); }
@ -335,6 +338,8 @@ private:
ldb::ReadOptions m_readOptions;
ldb::WriteOptions m_writeOptions;
std::function<void(Exception&)> m_onBad; ///< Called if we have a block that doesn't verify.
friend std::ostream& operator<<(std::ostream& _out, BlockChain const& _bc);
};

55
libethereum/BlockQueue.cpp

@ -26,6 +26,7 @@
#include <libethcore/Exceptions.h>
#include <libethcore/BlockInfo.h>
#include "BlockChain.h"
#include "State.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
@ -76,56 +77,44 @@ void BlockQueue::verifierBody()
std::pair<BlockInfo, bytes> res;
swap(work.second, res.second);
try {
try {
try
{
try
{
res.first.populate(res.second, CheckEverything, work.first);
res.first.verifyInternals(&res.second);
}
catch (InvalidBlockNonce&)
{
badBlock(res.second, "Invalid block nonce");
cwarn << " Nonce:" << res.first.nonce.hex();
cwarn << " PoWHash:" << res.first.headerHash(WithoutNonce).hex();
cwarn << " SeedHash:" << res.first.seedHash().hex();
cwarn << " Target:" << res.first.boundary().hex();
cwarn << " MixHash:" << res.first.mixHash.hex();
Ethash::Result er = EthashAux::eval(res.first.seedHash(), res.first.headerHash(WithoutNonce), res.first.nonce);
cwarn << " Ethash v:" << er.value.hex();
cwarn << " Ethash mH:" << er.mixHash.hex();
throw;
}
catch (Exception& _e)
catch (Exception& ex)
{
badBlock(res.second, _e.what());
clog(BlockChainNote) << " Malformed block: " << diagnostic_information(ex);
badBlock(res.second, ex.what());
ex << errinfo_now(time(0));
ex << errinfo_block(res.second);
if (m_onBad)
m_onBad(ex);
throw;
}
RLP r(&res.second);
unsigned ii = 0;
for (auto const& uncle: r[2])
{
try
{
BlockInfo().populateFromHeader(RLP(uncle.data()), CheckEverything);
}
catch (InvalidNonce&)
{
badBlockHeader(uncle.data(), "Invalid uncle nonce");
BlockInfo bi = BlockInfo::fromHeader(uncle.data(), CheckNothing);
cwarn << " Nonce:" << bi.nonce.hex();
cwarn << " PoWHash:" << bi.headerHash(WithoutNonce).hex();
cwarn << " SeedHash:" << bi.seedHash().hex();
cwarn << " Target:" << bi.boundary().hex();
cwarn << " MixHash:" << bi.mixHash.hex();
Ethash::Result er = EthashAux::eval(bi.seedHash(), bi.headerHash(WithoutNonce), bi.nonce);
cwarn << " Ethash v:" << er.value.hex();
cwarn << " Ethash mH:" << er.mixHash.hex();
throw;
}
catch (Exception& _e)
catch (Exception& ex)
{
badBlockHeader(uncle.data(), _e.what());
clog(BlockChainNote) << " Malformed block header: " << diagnostic_information(ex);
badBlockHeader(uncle.data(), ex.what());
ex << errinfo_uncleIndex(ii);
ex << errinfo_now(time(0));
ex << errinfo_block(res.second);
if (m_onBad)
m_onBad(ex);
throw;
}
++ii;
}
}
catch (...)

4
libethereum/BlockQueue.h

@ -110,6 +110,8 @@ public:
template <class T> Handler onReady(T const& _t) { return m_onReady.add(_t); }
template <class T> void setOnBad(T const& _t) { m_onBad = _t; }
private:
void noteReady_WITH_LOCK(h256 const& _b);
@ -134,6 +136,8 @@ private:
std::vector<std::thread> m_verifiers; ///< Threads who only verify.
bool m_deleting = false; ///< Exit condition for verifiers.
std::function<void(Exception&)> m_onBad; ///< Called if we have a block that doesn't verify.
};
std::ostream& operator<<(std::ostream& _out, BlockQueueStatus const& _s);

7
libethereum/CMakeLists.txt

@ -14,6 +14,10 @@ aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..)
include_directories(${LEVELDB_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
if (JSONRPC)
include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
endif()
set(EXECUTABLE ethereum)
@ -30,6 +34,9 @@ target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_REGEX_LIBRARIES})
target_link_libraries(${EXECUTABLE} secp256k1)
if (JSONRPC)
target_link_libraries(${EXECUTABLE} ${JSON_RPC_CPP_CLIENT_LIBRARIES})
endif()
if (CMAKE_COMPILER_IS_MINGW)
target_link_libraries(${EXECUTABLE} ssp shlwapi)

167
libethereum/Client.cpp

@ -25,9 +25,16 @@
#include <thread>
#include <boost/filesystem.hpp>
#include <boost/math/distributions/normal.hpp>
#if ETH_JSONRPC || !ETH_TRUE
#include <jsonrpccpp/client.h>
#include <jsonrpccpp/client/connectors/httpclient.h>
#endif
#include <libdevcore/Log.h>
#include <libdevcore/StructuredLogger.h>
#include <libp2p/Host.h>
#if ETH_JSONRPC || !ETH_TRUE
#include "Sentinel.h"
#endif
#include "Defaults.h"
#include "Executive.h"
#include "EthereumHost.h"
@ -80,6 +87,101 @@ void VersionChecker::setOk()
}
}
void Client::onBadBlock(Exception& _ex)
{
// BAD BLOCK!!!
bytes const& block = *boost::get_error_info<errinfo_block>(_ex);
if (!&block)
{
cwarn << "ODD: onBadBlock called but exception has no block in it.";
return;
}
badBlock(block, _ex.what());
cwarn << boost::diagnostic_information(_ex, true);
#if ETH_JSONRPC || !ETH_TRUE
if (!m_sentinel.empty())
{
Json::Value report;
report["client"] = "cpp";
report["version"] = Version;
report["protocolVersion"] = c_protocolVersion;
report["databaseVersion"] = c_databaseVersion;
report["errortype"] = _ex.what();
report["block"] = toHex(block);
report["hint"] = Json::Value(Json::objectValue);
// add the various hints.
if (unsigned const* uncleIndex = boost::get_error_info<errinfo_uncleIndex>(_ex))
{
// uncle that failed.
report["hints"]["uncleIndex"] = *uncleIndex;
}
else if (unsigned const* txIndex = boost::get_error_info<errinfo_transactionIndex>(_ex))
{
// transaction that failed.
report["hints"]["transactionIndex"] = *txIndex;
}
else
{
// general block failure.
}
if (string const* vmtraceJson = boost::get_error_info<errinfo_vmtrace>(_ex))
Json::Reader().parse(*vmtraceJson, report["hints"]["vmtrace"]);
if (vector<bytes> const* receipts = boost::get_error_info<errinfo_receipts>(_ex))
{
report["hints"]["receipts"] = Json::arrayValue;
for (auto const& r: *receipts)
report["hints"]["receipts"].append(toHex(r));
}
if (h256Hash const* excluded = boost::get_error_info<errinfo_unclesExcluded>(_ex))
{
report["hints"]["unclesExcluded"] = Json::arrayValue;
for (auto const& r: h256Set() + *excluded)
report["hints"]["unclesExcluded"].append(Json::Value(r.hex()));
}
#define DEV_HINT_ERRINFO(X) \
if (auto const* n = boost::get_error_info<errinfo_ ## X>(_ex)) \
report["hints"][#X] = toString(*n)
#define DEV_HINT_ERRINFO_HASH(X) \
if (auto const* n = boost::get_error_info<errinfo_ ## X>(_ex)) \
report["hints"][#X] = n->hex()
DEV_HINT_ERRINFO_HASH(hash256);
DEV_HINT_ERRINFO(uncleNumber);
DEV_HINT_ERRINFO(currentNumber);
DEV_HINT_ERRINFO(now);
DEV_HINT_ERRINFO(invalidSymbol);
DEV_HINT_ERRINFO(wrongAddress);
DEV_HINT_ERRINFO(comment);
DEV_HINT_ERRINFO(min);
DEV_HINT_ERRINFO(max);
DEV_HINT_ERRINFO(required);
DEV_HINT_ERRINFO(got);
DEV_HINT_ERRINFO_HASH(required_LogBloom);
DEV_HINT_ERRINFO_HASH(got_LogBloom);
DEV_HINT_ERRINFO_HASH(required_h256);
DEV_HINT_ERRINFO_HASH(got_h256);
jsonrpc::HttpClient client(m_sentinel);
Sentinel rpc(client);
try
{
rpc.eth_badBlock(report);
}
catch (...)
{
cwarn << "Error reporting to sentinel. Sure the address" << m_sentinel << "is correct?";
}
}
#endif
}
void BasicGasPricer::update(BlockChain const& _bc)
{
unsigned c = 0;
@ -185,6 +287,8 @@ Client::Client(p2p::Host* _extNet, std::shared_ptr<GasPricer> _gp, std::string c
m_lastGetWork = std::chrono::system_clock::now() - chrono::seconds(30);
m_tqReady = m_tq.onReady([=](){ this->onTransactionQueueReady(); }); // TODO: should read m_tq->onReady(thisThread, syncTransactionQueue);
m_bqReady = m_bq.onReady([=](){ this->onBlockQueueReady(); }); // TODO: should read m_bq->onReady(thisThread, syncBlockQueue);
m_bq.setOnBad([=](Exception& ex){ this->onBadBlock(ex); });
m_bc.setOnBad([=](Exception& ex){ this->onBadBlock(ex); });
m_farm.onSolutionFound([=](ProofOfWork::Solution const& s){ return this->submitWork(s); });
m_gp->update(m_bc);
@ -206,6 +310,18 @@ Client::~Client()
stopWorking();
}
static const Address c_canary("0x");
bool Client::isChainBad() const
{
return stateAt(c_canary, 0) != 0;
}
bool Client::isUpgradeNeeded() const
{
return stateAt(c_canary, 0) == 2;
}
void Client::setNetworkId(u256 _n)
{
if (auto h = m_host.lock())
@ -448,6 +564,9 @@ ProofOfWork::WorkPackage Client::getWork()
bool oldShould = shouldServeWork();
m_lastGetWork = chrono::system_clock::now();
if (!m_mineOnBadChain && isChainBad())
return ProofOfWork::WorkPackage();
// if this request has made us bother to serve work, prep it now.
if (!oldShould && shouldServeWork())
onPostStateChanged();
@ -605,11 +724,22 @@ bool Client::remoteActive() const
void Client::onPostStateChanged()
{
cnote << "Post state changed";
cnote << "Post state changed.";
rejigMining();
m_remoteWorking = false;
}
void Client::startMining()
{
m_wouldMine = true;
rejigMining();
}
if (m_bq.items().first == 0 && (isMining() || remoteActive()))
void Client::rejigMining()
{
if ((wouldMine() || remoteActive()) && !m_bq.items().first && (!isChainBad() || mineOnBadChain()) /*&& (forceMining() || transactionsWaiting())*/)
{
cnote << "Restarting mining...";
cnote << "Rejigging mining...";
DEV_WRITE_GUARDED(x_working)
m_working.commitToMine(m_bc);
DEV_READ_GUARDED(x_working)
@ -618,20 +748,21 @@ void Client::onPostStateChanged()
m_postMine = m_working;
m_miningInfo = m_postMine.info();
}
m_farm.setWork(m_miningInfo);
Ethash::ensurePrecomputed(m_bc.number());
}
m_remoteWorking = false;
}
if (m_wouldMine)
{
m_farm.setWork(m_miningInfo);
if (m_turboMining)
m_farm.startGPU();
else
m_farm.startCPU();
void Client::startMining()
{
if (m_turboMining)
m_farm.startGPU();
else
m_farm.startCPU();
onPostStateChanged();
m_farm.setWork(m_miningInfo);
Ethash::ensurePrecomputed(m_bc.number());
}
}
if (!m_wouldMine)
m_farm.stop();
}
void Client::noteChanged(h256Hash const& _filters)
@ -746,3 +877,9 @@ void Client::flushTransactions()
{
doWork();
}
HashChainStatus Client::hashChainStatus() const
{
auto h = m_host.lock();
return h ? h->status() : HashChainStatus { 0, 0, false };
}

35
libethereum/Client.h

@ -143,7 +143,7 @@ public:
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(); }
virtual u256 gasLimitRemaining() const override { return m_postMine.gasLimitRemaining(); }
// [PRIVATE API - only relevant for base clients, not available in general]
dev::eth::State state(unsigned _txi, h256 _block) const;
@ -156,10 +156,14 @@ public:
CanonBlockChain const& blockChain() const { return m_bc; }
/// Get some information on the block queue.
BlockQueueStatus blockQueueStatus() const { return m_bq.status(); }
/// Get some information on the block queue.
HashChainStatus hashChainStatus() const;
/// Get the block queue.
BlockQueue const& blockQueue() const { return m_bq; }
// Mining stuff:
void setAddress(Address _us) { WriteGuard l(x_preMine); m_preMine.setAddress(_us); }
virtual void setAddress(Address _us) override { WriteGuard l(x_preMine); m_preMine.setAddress(_us); }
/// Check block validity prior to mining.
bool miningParanoia() const { return m_paranoia; }
@ -174,14 +178,26 @@ public:
/// Enable/disable GPU mining.
void setTurboMining(bool _enable = true) { m_turboMining = _enable; if (isMining()) startMining(); }
/// Check to see if we'd mine on an apparently bad chain.
bool mineOnBadChain() const { return m_mineOnBadChain; }
/// Set true if you want to mine even when the canary says you're on the wrong chain.
void setMineOnBadChain(bool _v) { m_mineOnBadChain = _v; }
/// @returns true if the canary says that the chain is bad.
bool isChainBad() const;
/// @returns true if the canary says that the client should be upgraded.
bool isUpgradeNeeded() const;
/// Start mining.
/// NOT thread-safe - call it & stopMining only from a single thread
void startMining() override;
/// Stop mining.
/// NOT thread-safe
void stopMining() override { m_farm.stop(); }
void stopMining() override { m_wouldMine = false; rejigMining(); }
/// Are we mining now?
bool isMining() const override { return m_farm.isMining(); }
/// Are we mining now?
bool wouldMine() const override { return m_wouldMine; }
/// The hashrate...
uint64_t hashrate() const override;
/// Check the progress of the mining.
@ -213,6 +229,8 @@ public:
void retryUnkonwn() { m_bq.retryAllUnknown(); }
/// Get a report of activity.
ActivityReport activityReport() { ActivityReport ret; std::swap(m_report, ret); return ret; }
/// Set a JSONRPC server to which we can report bad blocks.
void setSentinel(std::string const& _server) { m_sentinel = _server; }
protected:
/// InterfaceStub methods
@ -249,6 +267,9 @@ private:
/// Called when Worker is exiting.
void doneWorking() override;
/// Called when wouldMine(), turboMining(), isChainBad(), forceMining(), pendingTransactions() have changed.
void rejigMining();
/// Magically called when the chain has changed. An import route is provided.
/// Called by either submitWork() or in our main thread through syncBlockQueue().
void onChainChanged(ImportRoute const& _ir);
@ -278,6 +299,10 @@ private:
/// @returns true only if it's worth bothering to prep the mining block.
bool shouldServeWork() const { return m_bq.items().first == 0 && (isMining() || remoteActive()); }
/// Called when we have attempted to import a bad block.
/// @warning May be called from any thread.
void onBadBlock(Exception& _ex);
VersionChecker m_vc; ///< Dummy object to check & update the protocol version.
CanonBlockChain m_bc; ///< Maintains block database.
BlockQueue m_bq; ///< Maintains a list of incoming blocks not yet on the blockchain (to be imported).
@ -302,8 +327,10 @@ private:
Handler m_tqReady;
Handler m_bqReady;
bool m_wouldMine = false; ///< True if we /should/ be mining.
bool m_turboMining = false; ///< Don't squander all of our time mining actually just sleeping.
bool m_forceMining = false; ///< Mine even when there are no transactions pending?
bool m_mineOnBadChain = false; ///< Mine even when the canary says it's a bad chain.
bool m_paranoia = false; ///< Should we be paranoid about our state?
mutable std::chrono::system_clock::time_point m_lastGarbageCollection;
@ -317,6 +344,8 @@ private:
Mutex x_signalled;
std::atomic<bool> m_syncTransactionQueue = {false};
std::atomic<bool> m_syncBlockQueue = {false};
std::string m_sentinel;
};
}

5
libethereum/ClientBase.cpp

@ -400,17 +400,16 @@ h256s ClientBase::pendingHashes() const
return h256s() + postMine().pendingHashes();
}
StateDiff ClientBase::diff(unsigned _txi, h256 _block) const
{
State st = asOf(_block);
return st.fromPending(_txi).diff(st.fromPending(_txi + 1));
return st.fromPending(_txi).diff(st.fromPending(_txi + 1), true);
}
StateDiff ClientBase::diff(unsigned _txi, BlockNumber _block) const
{
State st = asOf(_block);
return st.fromPending(_txi).diff(st.fromPending(_txi + 1));
return st.fromPending(_txi).diff(st.fromPending(_txi + 1), true);
}
Addresses ClientBase::addresses(BlockNumber _block) const

8
libethereum/ClientBase.h

@ -132,8 +132,8 @@ public:
virtual Transactions pending() const override;
virtual h256s pendingHashes() const override;
ImportResult injectTransaction(bytes const& _rlp) override { prepareForTransaction(); return m_tq.import(_rlp); }
ImportResult injectBlock(bytes const& _block);
virtual ImportResult injectTransaction(bytes const& _rlp) override { prepareForTransaction(); return m_tq.import(_rlp); }
virtual ImportResult injectBlock(bytes const& _block) override;
using Interface::diff;
virtual StateDiff diff(unsigned _txi, h256 _block) const override;
@ -143,9 +143,6 @@ public:
virtual Addresses addresses(BlockNumber _block) const override;
virtual u256 gasLimitRemaining() const override;
/// Set the coinbase address
virtual void setAddress(Address _us) = 0;
/// Get the coinbase address
virtual Address address() const override;
@ -154,6 +151,7 @@ public:
virtual void startMining() override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::startMining")); }
virtual void stopMining() override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::stopMining")); }
virtual bool isMining() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::isMining")); }
virtual bool wouldMine() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::wouldMine")); }
virtual uint64_t hashrate() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::hashrate")); }
virtual MiningProgress miningProgress() const override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::miningProgress")); }
virtual ProofOfWork::WorkPackage getWork() override { BOOST_THROW_EXCEPTION(InterfaceNotSupported("ClientBase::getWork")); }

13
libethereum/CommonNet.h

@ -38,14 +38,16 @@ namespace eth
#if ETH_DEBUG
static const unsigned c_maxHashes = 2048; ///< Maximum number of hashes BlockHashes will ever send.
static const unsigned c_maxHashesAsk = 2048; ///< Maximum number of hashes GetBlockHashes will ever ask for.
static const unsigned c_maxHashesAsk = 256; ///< Maximum number of hashes GetBlockHashes will ever ask for.
static const unsigned c_maxBlocks = 128; ///< Maximum number of blocks Blocks will ever send.
static const unsigned c_maxBlocksAsk = 128; ///< Maximum number of blocks we ask to receive in Blocks (when using GetChain).
static const unsigned c_maxBlocksAsk = 8; ///< Maximum number of blocks we ask to receive in Blocks (when using GetChain).
static const unsigned c_maxPayload = 262144; ///< Maximum size of packet for us to send.
#else
static const unsigned c_maxHashes = 2048; ///< Maximum number of hashes BlockHashes will ever send.
static const unsigned c_maxHashesAsk = 2048; ///< Maximum number of hashes GetBlockHashes will ever ask for.
static const unsigned c_maxBlocks = 128; ///< Maximum number of blocks Blocks will ever send.
static const unsigned c_maxBlocksAsk = 128; ///< Maximum number of blocks we ask to receive in Blocks (when using GetChain).
static const unsigned c_maxPayload = 262144; ///< Maximum size of packet for us to send.
#endif
class BlockChain;
@ -82,5 +84,12 @@ enum class Syncing
Done
};
struct HashChainStatus
{
unsigned total;
unsigned received;
bool estimated;
};
}
}

7
libethereum/DownloadMan.cpp

@ -80,7 +80,6 @@ HashDownloadSub::HashDownloadSub(HashDownloadMan& _man): m_man(&_man)
{
WriteGuard l(m_man->x_subs);
m_asked = RangeMask<unsigned>(m_man->m_chainStart, m_man->m_chainStart + m_man->m_chainCount);
m_attempted = RangeMask<unsigned>(m_man->m_chainStart, m_man->m_chainStart + m_man->m_chainCount);
m_man->m_subs.insert(this);
}
@ -98,7 +97,6 @@ void HashDownloadSub::resetFetch()
Guard l(m_fetch);
m_remaining = 0;
m_asked = RangeMask<unsigned>(m_man->m_chainStart, m_man->m_chainStart + m_man->m_chainCount);
m_attempted = RangeMask<unsigned>(m_man->m_chainStart, m_man->m_chainStart + m_man->m_chainCount);
}
unsigned HashDownloadSub::nextFetch(unsigned _n)
@ -110,10 +108,9 @@ unsigned HashDownloadSub::nextFetch(unsigned _n)
if (!m_man || m_man->chainEmpty())
return 0;
m_asked = (~(m_man->taken() + m_attempted)).lowest(_n);
m_asked = (~(m_man->taken())).lowest(_n);
if (m_asked.empty())
m_asked = (~(m_man->taken(true) + m_attempted)).lowest(_n);
m_attempted += m_asked;
m_asked = (~(m_man->taken(true))).lowest(_n);
return *m_asked.begin();
}

8
libethereum/DownloadMan.h

@ -187,7 +187,6 @@ public:
bool askedContains(unsigned _i) const { Guard l(m_fetch); return m_asked.contains(_i); }
RangeMask<unsigned> const& asked() const { return m_asked; }
RangeMask<unsigned> const& attemped() const { return m_attempted; }
private:
void resetFetch(); // Called by DownloadMan when we need to reset the download.
@ -196,7 +195,6 @@ private:
mutable Mutex m_fetch;
unsigned m_remaining;
RangeMask<unsigned> m_asked;
RangeMask<unsigned> m_attempted;
};
class HashDownloadMan
@ -255,6 +253,11 @@ public:
return m_got.full();
}
unsigned gotCount() const
{
return m_got.size();
}
size_t chainSize() const { ReadGuard l(m_lock); return m_chainCount; }
size_t chainEmpty() const { ReadGuard l(m_lock); return m_chainCount == 0; }
void foreachSub(std::function<void(HashDownloadSub const&)> const& _f) const { ReadGuard l(x_subs); for(auto i: m_subs) _f(*i); }
@ -274,3 +277,4 @@ private:
}
}

113
libethereum/EthereumHost.cpp

@ -237,7 +237,7 @@ void EthereumHost::maintainBlocks(h256 const& _currentHash)
void EthereumHost::onPeerStatus(EthereumPeer* _peer)
{
Guard l(x_sync);
RecursiveGuard l(x_sync);
if (_peer->m_genesisHash != m_chain.genesisHash())
_peer->disable("Invalid genesis hash");
else if (_peer->m_protocolVersion != protocolVersion() && _peer->m_protocolVersion != c_oldProtocolVersion)
@ -252,10 +252,13 @@ void EthereumHost::onPeerStatus(EthereumPeer* _peer)
{
if (_peer->m_protocolVersion != protocolVersion())
estimatePeerHashes(_peer);
else if (_peer->m_latestBlockNumber > m_chain.number())
_peer->m_expectedHashes = (unsigned)_peer->m_latestBlockNumber - m_chain.number();
if (m_hashMan.chainSize() < _peer->m_expectedHashes)
m_hashMan.resetToRange(m_chain.number() + 1, _peer->m_expectedHashes);
else
{
if (_peer->m_latestBlockNumber > m_chain.number())
_peer->m_expectedHashes = (unsigned)_peer->m_latestBlockNumber - m_chain.number();
if (m_hashMan.chainSize() < _peer->m_expectedHashes)
m_hashMan.resetToRange(m_chain.number() + 1, _peer->m_expectedHashes);
}
continueSync(_peer);
}
}
@ -265,7 +268,7 @@ void EthereumHost::estimatePeerHashes(EthereumPeer* _peer)
BlockInfo block = m_chain.info();
time_t lastBlockTime = (block.hash() == m_chain.genesisHash()) ? 1428192000 : (time_t)block.timestamp;
time_t now = time(0);
unsigned blockCount = 1000;
unsigned blockCount = 30000;
if (lastBlockTime > now)
clog(NetWarn) << "Clock skew? Latest block is in the future";
else
@ -274,9 +277,16 @@ void EthereumHost::estimatePeerHashes(EthereumPeer* _peer)
_peer->m_expectedHashes = blockCount;
}
void EthereumHost::noteRude(p2p::NodeId const& _id, std::string const& _client)
{
cwarn << "RUDE node/client: " << _id << _client;
m_rudeNodes.insert(_id);
m_rudeClients.insert(_client);
}
void EthereumHost::onPeerHashes(EthereumPeer* _peer, h256s const& _hashes)
{
Guard l(x_sync);
RecursiveGuard l(x_sync);
assert(_peer->m_asking == Asking::Nothing);
onPeerHashes(_peer, _hashes, false);
}
@ -285,13 +295,23 @@ void EthereumHost::onPeerHashes(EthereumPeer* _peer, h256s const& _hashes, bool
{
if (_hashes.empty())
{
onPeerDoneHashes(_peer, true);
_peer->m_hashSub.doneFetch();
continueSync();
return;
}
bool syncByNumber = _peer->m_syncHashNumber;
if (!syncByNumber && _peer->m_syncHash != m_syncingLatestHash)
{
// Obsolete hashes, discard
continueSync(_peer);
return;
}
unsigned knowns = 0;
unsigned unknowns = 0;
h256s neededBlocks;
bool syncByNumber = !m_syncingLatestHash;
unsigned firstNumber = _peer->m_syncHashNumber - _hashes.size();
for (unsigned i = 0; i < _hashes.size(); ++i)
{
_peer->addRating(1);
@ -321,8 +341,11 @@ void EthereumHost::onPeerHashes(EthereumPeer* _peer, h256s const& _hashes, bool
}
else
knowns++;
if (!syncByNumber)
m_syncingLatestHash = h;
else
_peer->m_hashSub.noteHash(firstNumber + i, 1);
}
if (syncByNumber)
{
@ -368,13 +391,14 @@ void EthereumHost::onPeerDoneHashes(EthereumPeer* _peer, bool _localChain)
{
m_man.resetToChain(m_hashes);
m_hashes.clear();
m_hashMan.reset(m_chain.number() + 1);
}
continueSync();
}
void EthereumHost::onPeerBlocks(EthereumPeer* _peer, RLP const& _r)
{
Guard l(x_sync);
RecursiveGuard l(x_sync);
assert(_peer->m_asking == Asking::Nothing);
unsigned itemCount = _r.itemCount();
clog(NetMessageSummary) << "Blocks (" << dec << itemCount << "entries)" << (itemCount ? "" : ": NoMoreBlocks");
@ -384,6 +408,7 @@ void EthereumHost::onPeerBlocks(EthereumPeer* _peer, RLP const& _r)
// Got to this peer's latest block - just give up.
clog(NetNote) << "Finishing blocks fetch...";
// NOTE: need to notify of giving up on chain-hashes, too, altering state as necessary.
_peer->m_sub.doneFetch();
_peer->setIdle();
return;
}
@ -450,7 +475,7 @@ void EthereumHost::onPeerBlocks(EthereumPeer* _peer, RLP const& _r)
void EthereumHost::onPeerNewHashes(EthereumPeer* _peer, h256s const& _hashes)
{
Guard l(x_sync);
RecursiveGuard l(x_sync);
if (isSyncing_UNSAFE())
{
clog(NetMessageSummary) << "Ignoring new hashes since we're already downloading.";
@ -462,7 +487,7 @@ void EthereumHost::onPeerNewHashes(EthereumPeer* _peer, h256s const& _hashes)
void EthereumHost::onPeerNewBlock(EthereumPeer* _peer, RLP const& _r)
{
Guard l(x_sync);
RecursiveGuard l(x_sync);
if (isSyncing_UNSAFE())
{
clog(NetMessageSummary) << "Ignoring new blocks since we're already downloading.";
@ -549,6 +574,17 @@ void EthereumHost::onPeerTransactions(EthereumPeer* _peer, RLP const& _r)
}
}
void EthereumHost::onPeerAborting(EthereumPeer* _peer)
{
RecursiveGuard l(x_sync);
if (_peer->isSyncing())
{
_peer->setIdle();
_peer->setRude();
continueSync();
}
}
void EthereumHost::continueSync()
{
clog(NetAllDetail) << "Getting help with downloading hashes and blocks";
@ -562,22 +598,37 @@ void EthereumHost::continueSync()
void EthereumHost::continueSync(EthereumPeer* _peer)
{
assert(_peer->m_asking == Asking::Nothing);
bool otherPeerSync = false;
bool otherPeerV60Sync = false;
bool otherPeerV61Sync = false;
if (m_needSyncHashes && peerShouldGrabChain(_peer))
{
foreachPeer([&](EthereumPeer* _p)
{
if (_p != _peer && _p->m_asking == Asking::Hashes && _p->m_protocolVersion != protocolVersion())
otherPeerSync = true; // Already have a peer downloading hash chain with old protocol, do nothing
if (_p != _peer && _p->m_asking == Asking::Hashes)
{
if (_p->m_protocolVersion != protocolVersion())
otherPeerV60Sync = true; // Already have a peer downloading hash chain with old protocol, do nothing
else
otherPeerV61Sync = true; // Already have a peer downloading hash chain with V61+ protocol, join if supported
}
});
if (otherPeerSync)
if (otherPeerV60Sync && !m_hashes.empty())
{
/// Downloading from other peer with v60 protocol, nothing else we can do
_peer->setIdle();
return;
}
if (otherPeerV61Sync && _peer->m_protocolVersion != protocolVersion())
{
/// Downloading from other peer with v60 protocol, nothing ese we can do
/// Downloading from other peer with v61+ protocol which this peer does not support,
_peer->setIdle();
return;
}
if (_peer->m_protocolVersion == protocolVersion() && !m_syncingLatestHash)
if (_peer->m_protocolVersion == protocolVersion() && !m_hashMan.isComplete())
{
m_syncingV61 = true;
_peer->requestHashes(); /// v61+ and not catching up to a particular hash
}
else
{
// Restart/continue sync in single peer mode
@ -586,7 +637,14 @@ void EthereumHost::continueSync(EthereumPeer* _peer)
m_syncingLatestHash =_peer->m_latestHash;
m_syncingTotalDifficulty = _peer->m_totalDifficulty;
}
_peer->requestHashes(m_syncingLatestHash);
if (_peer->m_totalDifficulty >= m_syncingTotalDifficulty)
{
_peer->requestHashes(m_syncingLatestHash);
m_syncingV61 = false;
m_estimatedHashes = _peer->m_expectedHashes;
}
else
_peer->setIdle();
}
}
else if (m_needSyncBlocks && peerShouldGrabBlocks(_peer)) // Check if this peer can help with downloading blocks
@ -597,6 +655,10 @@ void EthereumHost::continueSync(EthereumPeer* _peer)
bool EthereumHost::peerShouldGrabBlocks(EthereumPeer* _peer) const
{
// Early exit if this peer has proved unreliable.
if (_peer->isRude())
return false;
auto td = _peer->m_totalDifficulty;
auto lh = m_syncingLatestHash;
auto ctd = m_chain.details().totalDifficulty;
@ -609,6 +671,10 @@ bool EthereumHost::peerShouldGrabBlocks(EthereumPeer* _peer) const
bool EthereumHost::peerShouldGrabChain(EthereumPeer* _peer) const
{
// Early exit if this peer has proved unreliable.
if (_peer->isRude())
return false;
h256 c = m_chain.currentHash();
unsigned n = m_chain.number();
u256 td = m_chain.details().totalDifficulty;
@ -638,3 +704,12 @@ bool EthereumHost::isSyncing_UNSAFE() const
});
return syncing;
}
HashChainStatus EthereumHost::status()
{
RecursiveGuard l(x_sync);
if (m_syncingV61)
return HashChainStatus { static_cast<unsigned>(m_hashMan.chainSize()), static_cast<unsigned>(m_hashMan.gotCount()), false };
return HashChainStatus { m_estimatedHashes, static_cast<unsigned>(m_hashes.size()), true };
}

16
libethereum/EthereumHost.h

@ -70,8 +70,10 @@ public:
void reset();
DownloadMan const& downloadMan() const { return m_man; }
bool isSyncing() const { Guard l(x_sync); return isSyncing_UNSAFE(); }
bool isBanned(p2p::NodeId _id) const { return !!m_banned.count(_id); }
bool isSyncing() const { RecursiveGuard l(x_sync); return isSyncing_UNSAFE(); }
bool isBanned(p2p::NodeId const& _id) const { return !!m_banned.count(_id); }
void noteRude(p2p::NodeId const& _id, std::string const& _client);
bool isRude(p2p::NodeId const& _id, std::string const& _client) const { return m_rudeClients.count(_client) && m_rudeNodes.count(_id); }
void noteNewTransactions() { m_newTransactions = true; }
void noteNewBlocks() { m_newBlocks = true; }
@ -82,10 +84,12 @@ public:
void onPeerNewHashes(EthereumPeer* _peer, h256s const& _hashes); ///< Called by peer once it has new hashes
void onPeerHashes(EthereumPeer* _peer, h256s const& _hashes); ///< Called by peer once it has another sequential block of hashes during sync
void onPeerTransactions(EthereumPeer* _peer, RLP const& _r); ///< Called by peer when it has new transactions
void onPeerAborting(EthereumPeer* _peer); ///< Called by peer when it is disconnecting
DownloadMan& downloadMan() { return m_man; }
HashDownloadMan& hashDownloadMan() { return m_hashMan; }
BlockChain const& chain() { return m_chain; }
HashChainStatus status();
static unsigned const c_oldProtocolVersion;
@ -141,12 +145,16 @@ private:
bool m_newTransactions = false;
bool m_newBlocks = false;
mutable Mutex x_sync;
mutable RecursiveMutex x_sync;
bool m_needSyncHashes = true; ///< Indicates if need to downlad hashes
bool m_needSyncBlocks = true; ///< Indicates if we still need to download some blocks
h256 m_syncingLatestHash; ///< Latest block's hash, as of the current sync.
u256 m_syncingTotalDifficulty; ///< Latest block's total difficulty, as of the current sync.
h256s m_hashes; ///< List of hashes with unknown block numbers. Used for v60 chain downloading and catching up to a particular unknown
h256s m_hashes; ///< List of hashes with unknown block numbers. Used for PV60 chain downloading and catching up to a particular unknown
unsigned m_estimatedHashes = 0; ///< Number of estimated hashes for the last peer over PV60. Used for status reporting only.
bool m_syncingV61 = false; ///< True if recent activity was over pv61+. Used for status reporting only.
std::unordered_set<p2p::NodeId> m_rudeNodes; ///< Nodes that were impolite while syncing. We avoid syncing from these if possible.
std::unordered_set<std::string> m_rudeClients; ///< Nodes that were impolite while syncing. We avoid syncing from these if possible.
};
}

37
libethereum/EthereumPeer.cpp

@ -40,6 +40,8 @@ EthereumPeer::EthereumPeer(Session* _s, HostCapabilityFace* _h, unsigned _i, Cap
m_hashSub(host()->hashDownloadMan()),
m_peerCapabilityVersion(_cap.second)
{
m_isRude = host()->isRude(session()->id(), session()->info().clientVersion);
session()->addNote("manners", m_isRude ? "RUDE" : "nice");
m_syncHashNumber = host()->chain().number() + 1;
requestStatus();
}
@ -52,8 +54,14 @@ EthereumPeer::~EthereumPeer()
void EthereumPeer::abortSync()
{
if (isSyncing())
setIdle();
host()->onPeerAborting(this);
}
void EthereumPeer::setRude()
{
m_isRude = true;
host()->noteRude(session()->id(), session()->info().clientVersion);
session()->addNote("manners", m_isRude ? "RUDE" : "nice");
}
EthereumHost* EthereumPeer::host() const
@ -105,6 +113,7 @@ void EthereumPeer::requestHashes()
{
assert(m_asking == Asking::Nothing);
m_syncHashNumber = m_hashSub.nextFetch(c_maxHashesAsk);
m_syncHash = h256();
setAsking(Asking::Hashes);
RLPStream s;
prep(s, GetBlockHashesByNumberPacket, 2) << m_syncHashNumber << c_maxHashesAsk;
@ -119,6 +128,8 @@ void EthereumPeer::requestHashes(h256 const& _lastHash)
RLPStream s;
prep(s, GetBlockHashesPacket, 2) << _lastHash << c_maxHashesAsk;
clog(NetMessageDetail) << "Requesting block hashes staring from " << _lastHash;
m_syncHash = _lastHash;
m_syncHashNumber = 0;
sealAndSend(s);
}
@ -175,8 +186,16 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
m_genesisHash = _r[4].toHash<h256>();
if (m_peerCapabilityVersion == host()->protocolVersion())
{
m_protocolVersion = host()->protocolVersion();
m_latestBlockNumber = _r[5].toInt<u256>();
if (_r.itemCount() != 6)
{
clog(NetImpolite) << "Peer does not support PV61+ status extension.";
m_protocolVersion = EthereumHost::c_oldProtocolVersion;
}
else
{
m_protocolVersion = host()->protocolVersion();
m_latestBlockNumber = _r[5].toInt<u256>();
}
}
clog(NetMessageSummary) << "Status:" << m_protocolVersion << "/" << m_networkId << "/" << m_genesisHash << "/" << m_latestBlockNumber << ", TD:" << m_totalDifficulty << "=" << m_latestHash;
@ -240,12 +259,10 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
setAsking(Asking::Nothing);
h256s hashes(itemCount);
for (unsigned i = 0; i < itemCount; ++i)
{
hashes[i] = _r[i].toHash<h256>();
m_hashSub.noteHash(m_syncHashNumber + i, 1);
}
m_syncHashNumber += itemCount;
if (m_syncHashNumber > 0)
m_syncHashNumber += itemCount;
host()->onPeerHashes(this, hashes);
break;
}
@ -263,7 +280,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
// return the requested blocks.
bytes rlp;
unsigned n = 0;
for (unsigned i = 0; i < min(count, c_maxBlocks); ++i)
for (unsigned i = 0; i < min(count, c_maxBlocks) && rlp.size() < c_maxPayload; ++i)
{
auto h = _r[i].toHash<h256>();
if (host()->chain().isKnown(h))
@ -286,7 +303,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
case BlocksPacket:
{
if (m_asking != Asking::Blocks)
clog(NetWarn) << "Peer giving us blocks when we didn't ask for them.";
clog(NetImpolite) << "Peer giving us blocks when we didn't ask for them.";
else
{
setAsking(Asking::Nothing);

15
libethereum/EthereumPeer.h

@ -82,6 +82,12 @@ public:
/// Request blocks. Uses block download manager.
void requestBlocks();
/// Check if this node is rude.
bool isRude() const { return m_isRude; }
/// Set that it's a rude node.
void setRude();
private:
using p2p::Capability::sealAndSend;
@ -101,7 +107,7 @@ private:
void setAsking(Asking _g);
/// Do we presently need syncing with this peer?
bool needsSyncing() const { return !!m_latestHash; }
bool needsSyncing() const { return !isRude() && !!m_latestHash; }
/// Are we presently syncing with this peer?
bool isSyncing() const;
@ -128,8 +134,9 @@ private:
/// This is built as we ask for hashes. Once no more hashes are given, we present this to the
/// host who initialises the DownloadMan and m_sub becomes active for us to begin asking for blocks.
unsigned m_expectedHashes = 0; ///< Estimated upper bound of hashes to expect from this peer.
unsigned m_syncHashNumber = 0; ///< Number of latest hash we sync to
unsigned m_expectedHashes = 0; ///< Estimated upper bound of hashes to expect from this peer.
unsigned m_syncHashNumber = 0; ///< Number of latest hash we sync to (PV61+)
h256 m_syncHash; ///< Latest hash we sync to (PV60)
/// Once we're asking for blocks, this becomes in use.
DownloadSub m_sub;
@ -145,6 +152,8 @@ private:
h256Hash m_knownBlocks; ///< Blocks that the peer already knows about (that don't need to be sent to them).
Mutex x_knownTransactions;
h256Hash m_knownTransactions; ///< Transactions that the peer already knows of.
bool m_isRude; ///< True if this node has been rude in the past.
};
}

118
libethereum/Executive.cpp

@ -19,6 +19,9 @@
#include "Executive.h"
#include <boost/timer.hpp>
#if ETH_JSONRPC || !ETH_TRUE
#include <json/json.h>
#endif
#include <libdevcore/CommonIO.h>
#include <libevm/VMFactory.h>
#include <libevm/VM.h>
@ -34,6 +37,101 @@ using namespace dev::eth;
const char* VMTraceChannel::name() { return "EVM"; }
const char* ExecutiveWarnChannel::name() { return WarnChannel::name(); }
StandardTrace::StandardTrace():
m_trace(new Json::Value(Json::arrayValue))
{}
bool changesMemory(Instruction _inst)
{
return
_inst == Instruction::MSTORE ||
_inst == Instruction::MSTORE8 ||
_inst == Instruction::CALL ||
_inst == Instruction::CALLCODE ||
_inst == Instruction::SHA3 ||
_inst == Instruction::CALLDATACOPY ||
_inst == Instruction::CODECOPY ||
_inst == Instruction::EXTCODECOPY;
}
bool changesStorage(Instruction _inst)
{
return _inst == Instruction::SSTORE;
}
void StandardTrace::operator()(uint64_t _steps, Instruction inst, bigint newMemSize, bigint gasCost, bigint gas, VM* voidVM, ExtVMFace const* voidExt)
{
ExtVM const& ext = *static_cast<ExtVM const*>(voidExt);
VM& vm = *voidVM;
Json::Value r(Json::objectValue);
Json::Value stack(Json::arrayValue);
for (auto const& i: vm.stack())
stack.append(toHex(toCompactBigEndian(i), 1));
r["stack"] = stack;
bool newContext = false;
Instruction lastInst = Instruction::STOP;
if (m_lastInst.size() == ext.depth)
{
// starting a new context
assert(m_lastInst.size() == ext.depth);
m_lastInst.push_back(inst);
newContext = true;
}
else if (m_lastInst.size() == ext.depth + 2)
{
// returned from old context
m_lastInst.pop_back();
lastInst = m_lastInst.back();
}
else if (m_lastInst.size() == ext.depth + 1)
{
// continuing in previous context
lastInst = m_lastInst.back();
}
else
{
cwarn << "GAA!!! Tracing VM and more than one new/deleted stack frame between steps!";
cwarn << "Attmepting naive recovery...";
m_lastInst.resize(ext.depth + 1);
}
if (changesMemory(lastInst) || newContext)
{
Json::Value mem(Json::arrayValue);
for (auto const& i: vm.memory())
mem.append(toHex(toCompactBigEndian(i), 1));
r["memory"] = mem;
}
if (changesStorage(lastInst) || newContext)
{
Json::Value storage(Json::objectValue);
for (auto const& i: ext.state().storage(ext.myAddress))
storage[toHex(toCompactBigEndian(i.first), 1)] = toHex(toCompactBigEndian(i.second), 1);
r["storage"] = storage;
}
r["depth"] = ext.depth;
r["address"] = ext.myAddress.hex();
r["steps"] = (unsigned)_steps;
r["inst"] = (unsigned)inst;
r["pc"] = toString(vm.curPC());
r["gas"] = toString(gas);
r["gascost"] = toString(gasCost);
r["memexpand"] = toString(newMemSize);
m_trace->append(r);
}
string StandardTrace::json() const
{
return Json::FastWriter().write(*m_trace);
}
Executive::Executive(State& _s, BlockChain const& _bc, unsigned _level):
m_s(_s),
m_lastHashes(_bc.lastHashes((unsigned)_s.info().number - 1)),
@ -68,7 +166,7 @@ void Executive::initialize(Transaction const& _transaction)
if (!m_t.checkPayment())
{
clog(ExecutiveWarnChannel) << "Not enough gas to pay for the transaction: Require >" << m_t.gasRequired() << " Got" << m_t.gas();
m_excepted = TransactionException::OutOfGas;
m_excepted = TransactionException::OutOfGasBase;
BOOST_THROW_EXCEPTION(OutOfGasBase() << RequirementError(m_t.gasRequired(), (bigint)m_t.gas()));
}
@ -202,24 +300,6 @@ OnOpFunc Executive::simpleTrace()
};
}
OnOpFunc Executive::standardTrace(ostream& o_output)
{
return [&](uint64_t steps, Instruction inst, bigint newMemSize, bigint gasCost, bigint gas, VM* voidVM, ExtVMFace const* voidExt)
{
ExtVM const& ext = *static_cast<ExtVM const*>(voidExt);
VM& vm = *voidVM;
o_output << endl << " STACK" << endl;
for (auto i: vm.stack())
o_output << (h256)i << endl;
o_output << " MEMORY" << endl << ((vm.memory().size() > 1000) ? " mem size greater than 1000 bytes " : memDump(vm.memory()));
o_output << " STORAGE" << endl;
for (auto const& i: ext.state().storage(ext.myAddress))
o_output << showbase << hex << i.first << ": " << i.second << endl;
o_output << " < " << dec << ext.depth << " : " << ext.myAddress << " : #" << steps << " : " << hex << setw(4) << setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " : " << dec << gas << " : -" << dec << gasCost << " : " << newMemSize << "x32" << " >";
};
}
bool Executive::go(OnOpFunc const& _onOp)
{
if (m_ext)

18
libethereum/Executive.h

@ -26,6 +26,11 @@
#include "ExtVM.h"
#include "Transaction.h"
namespace Json
{
class Value;
}
namespace dev
{
namespace eth
@ -38,6 +43,19 @@ struct Manifest;
struct VMTraceChannel: public LogChannel { static const char* name(); static const int verbosity = 11; };
struct ExecutiveWarnChannel: public LogChannel { static const char* name(); static const int verbosity = 6; };
class StandardTrace
{
public:
StandardTrace();
void operator()(uint64_t _steps, Instruction _inst, bigint _newMemSize, bigint _gasCost, bigint _gas, VM* _vm, ExtVMFace const* _extVM);
std::string json() const;
private:
std::vector<Instruction> m_lastInst;
std::shared_ptr<Json::Value> m_trace;
};
/**
* @brief Message-call/contract-creation executor; useful for executing transactions.
*

2
libethereum/Interface.h

@ -196,6 +196,8 @@ public:
virtual void stopMining() = 0;
/// Are we mining now?
virtual bool isMining() const = 0;
/// Would we like to mine now?
virtual bool wouldMine() const = 0;
/// Current hash rate.
virtual uint64_t hashrate() const = 0;

8
libethereum/Precompiled.cpp

@ -55,9 +55,13 @@ void ecrecoverCode(bytesConstRef _in, bytesRef _out)
{
try
{
ret = sha3(recover(sig, in.hash));
Public rec = recover(sig, in.hash);
if (rec)
ret = dev::sha3(rec);
else
return;
}
catch (...) {}
catch (...) { return; }
}
}

31
libethereum/Sentinel.h

@ -0,0 +1,31 @@
/**
* This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY!
*/
#ifndef JSONRPC_CPP_STUB_DEV_ETH_SENTINEL_H_
#define JSONRPC_CPP_STUB_DEV_ETH_SENTINEL_H_
#include <jsonrpccpp/client.h>
namespace dev {
namespace eth {
class Sentinel : public jsonrpc::Client
{
public:
Sentinel(jsonrpc::IClientConnector &conn, jsonrpc::clientVersion_t type = jsonrpc::JSONRPC_CLIENT_V2) : jsonrpc::Client(conn, type) {}
int eth_badBlock(const Json::Value& param1) throw (jsonrpc::JsonRpcException)
{
Json::Value p;
p.append(param1);
Json::Value result = this->CallMethod("eth_badBlock",p);
if (result.isInt())
return result.asInt();
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
};
}
}
#endif //JSONRPC_CPP_STUB_DEV_ETH_SENTINEL_H_

3
libethereum/Sentinel.json

@ -0,0 +1,3 @@
[
{ "name": "eth_badBlock", "params": [ {} ], "order": [], "returns": 0 }
]

157
libethereum/State.cpp

@ -158,6 +158,7 @@ State::State(State const& _s):
m_transactions(_s.m_transactions),
m_receipts(_s.m_receipts),
m_transactionSet(_s.m_transactionSet),
m_touched(_s.m_touched),
m_cache(_s.m_cache),
m_previousBlock(_s.m_previousBlock),
m_currentBlock(_s.m_currentBlock),
@ -206,7 +207,7 @@ State::~State()
{
}
StateDiff State::diff(State const& _c) const
StateDiff State::diff(State const& _c, bool _quick) const
{
StateDiff ret;
@ -217,19 +218,29 @@ StateDiff State::diff(State const& _c) const
auto trie = SecureTrieDB<Address, OverlayDB>(const_cast<OverlayDB*>(&m_db), rootHash());
auto trieD = SecureTrieDB<Address, OverlayDB>(const_cast<OverlayDB*>(&_c.m_db), _c.rootHash());
for (auto i: trie)
ads.insert(i.first), trieAds.insert(i.first);
for (auto i: trieD)
ads.insert(i.first), trieAdsD.insert(i.first);
for (auto i: m_cache)
if (_quick)
{
trieAds = m_touched;
trieAdsD = _c.m_touched;
(ads += m_touched) += _c.m_touched;
}
else
{
for (auto const& i: trie)
ads.insert(i.first), trieAds.insert(i.first);
for (auto const& i: trieD)
ads.insert(i.first), trieAdsD.insert(i.first);
}
for (auto const& i: m_cache)
ads.insert(i.first);
for (auto i: _c.m_cache)
for (auto const& i: _c.m_cache)
ads.insert(i.first);
// cnote << *this;
// cnote << _c;
for (auto i: ads)
for (auto const& i: ads)
{
auto it = m_cache.find(i);
auto itD = _c.m_cache.find(i);
@ -272,7 +283,7 @@ void State::ensureCached(std::unordered_map<Address, Account>& _cache, Address _
void State::commit()
{
dev::eth::commit(m_cache, m_db, m_state);
m_touched += dev::eth::commit(m_cache, m_db, m_state);
m_cache.clear();
}
@ -450,6 +461,7 @@ void State::resetCurrent()
m_receipts.clear();
m_transactionSet.clear();
m_cache.clear();
m_touched.clear();
m_currentBlock = BlockInfo();
m_currentBlock.coinbaseAddress = m_ourAddress;
m_currentBlock.timestamp = max(m_previousBlock.timestamp + 1, (u256)time(0));
@ -577,19 +589,20 @@ string State::vmTrace(bytesConstRef _block, BlockChain const& _bc, ImportRequire
LastHashes lh = _bc.lastHashes((unsigned)m_previousBlock.number);
vector<bytes> receipts;
ostringstream ss;
string ret;
unsigned i = 0;
for (auto const& tr: rlp[1])
{
ss << " VM Execution of transaction" << i << ":" << endl;
execute(lh, Transaction(tr.data(), CheckTransaction::Everything), Permanence::Committed, Executive::standardTrace(ss));
StandardTrace st;
execute(lh, Transaction(tr.data(), CheckTransaction::Everything), Permanence::Committed, [&](uint64_t _steps, Instruction _inst, bigint _newMemSize, bigint _gasCost, bigint _gas, VM* _vm, ExtVMFace const* _extVM) { st(_steps, _inst, _newMemSize, _gasCost, _gas, _vm, _extVM); });
ret += (ret.empty() ? "[" : ",") + st.json();
RLPStream receiptRLP;
m_receipts.back().streamRLP(receiptRLP);
receipts.push_back(receiptRLP.out());
++i;
ss << endl;
}
return ss.str();
return ret.empty() ? "[]" : (ret + "]");
}
u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirements::value _ir)
@ -605,6 +618,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
#endif
if (m_currentBlock.parentHash != m_previousBlock.hash())
// Internal client error.
BOOST_THROW_EXCEPTION(InvalidParentHash());
// Populate m_currentBlock with the correct values.
@ -624,16 +638,19 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
unsigned i = 0;
for (auto const& tr: rlp[1])
{
try {
try
{
LogOverride<ExecutiveWarnChannel> o(false);
execute(lh, Transaction(tr.data(), CheckTransaction::Everything));
}
catch (...)
catch (Exception& ex)
{
badBlock(_block, "Invalid transaction");
badBlock(_block, "Invalid transaction: " + toString(toTransactionException(ex)));
cwarn << " Transaction Index:" << i;
LogOverride<ExecutiveWarnChannel> o(true);
execute(lh, Transaction(tr.data(), CheckTransaction::Everything));
DEV_IGNORE_EXCEPTIONS(execute(lh, Transaction(tr.data(), CheckTransaction::Everything)));
ex << errinfo_transactionIndex(i);
throw;
}
@ -658,7 +675,12 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
cwarn << " " << TransactionReceipt(&b);
}
cwarn << " VMTrace:\n" << vmTrace(_block, _bc, _ir);
BOOST_THROW_EXCEPTION(InvalidReceiptsStateRoot());
InvalidReceiptsStateRoot ex;
ex << Hash256RequirementError(receiptsRoot, m_currentBlock.receiptsRoot);
ex << errinfo_receipts(receipts);
ex << errinfo_vmtrace(vmTrace(_block, _bc, _ir));
BOOST_THROW_EXCEPTION(ex);
}
if (m_currentBlock.logBloom != logBloom())
@ -671,7 +693,10 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
cwarn << " " << j << ":" << TransactionReceipt(&b).bloom().hex();
}
cwarn << " Final bloom:" << m_currentBlock.logBloom.hex();
BOOST_THROW_EXCEPTION(InvalidLogBloom());
InvalidLogBloom ex;
ex << LogBloomRequirementError(logBloom(), m_currentBlock.logBloom);
ex << errinfo_receipts(receipts);
BOOST_THROW_EXCEPTION(ex);
}
// Initialise total difficulty calculation.
@ -681,45 +706,70 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
if (rlp[2].itemCount() > 2)
{
badBlock(_block, "Too many uncles");
BOOST_THROW_EXCEPTION(TooManyUncles());
BOOST_THROW_EXCEPTION(TooManyUncles() << errinfo_max(2) << errinfo_got(rlp[2].itemCount()));
}
vector<BlockInfo> rewarded;
h256Hash excluded = _bc.allKinFrom(m_currentBlock.parentHash, 6);
excluded.insert(m_currentBlock.hash());
unsigned ii = 0;
for (auto const& i: rlp[2])
{
auto h = sha3(i.data());
if (excluded.count(h))
try
{
badBlock(_block, "Invalid uncle included");
BOOST_THROW_EXCEPTION(UncleInChain() << errinfo_comment("Uncle in block already mentioned") << errinfo_data(toString(excluded)) << errinfo_hash256(sha3(i.data())));
}
excluded.insert(h);
auto h = sha3(i.data());
if (excluded.count(h))
{
badBlock(_block, "Invalid uncle included");
UncleInChain ex;
ex << errinfo_comment("Uncle in block already mentioned");
ex << errinfo_unclesExcluded(excluded);
ex << errinfo_hash256(sha3(i.data()));
BOOST_THROW_EXCEPTION(ex);
}
excluded.insert(h);
BlockInfo uncle = BlockInfo::fromHeader(i.data(), (_ir & ImportRequirements::CheckUncles) ? CheckEverything : IgnoreNonce, h);
BlockInfo uncleParent(_bc.block(uncle.parentHash));
if ((bigint)uncleParent.number < (bigint)m_currentBlock.number - 7)
{
badBlock(_block, "Uncle too old");
cwarn << " Uncle number: " << uncle.number;
cwarn << " Uncle parent number: " << uncleParent.number;
cwarn << " Block number: " << m_currentBlock.number;
BOOST_THROW_EXCEPTION(UncleTooOld());
BlockInfo uncle;
BlockInfo uncleParent;
uncle = BlockInfo::fromHeader(i.data(), (_ir & ImportRequirements::CheckUncles) ? CheckEverything : IgnoreNonce, h);
if (!_bc.isKnown(uncle.parentHash))
BOOST_THROW_EXCEPTION(UnknownParent());
uncleParent = BlockInfo(_bc.block(uncle.parentHash));
if ((bigint)uncleParent.number < (bigint)m_currentBlock.number - 7)
{
badBlock(_block, "Uncle too old");
cwarn << " Uncle number: " << uncle.number;
cwarn << " Uncle parent number: " << uncleParent.number;
cwarn << " Block number: " << m_currentBlock.number;
UncleTooOld ex;
ex << errinfo_uncleNumber(uncle.number);
ex << errinfo_currentNumber(m_currentBlock.number);
BOOST_THROW_EXCEPTION(ex);
}
else if (uncle.number == m_currentBlock.number)
{
badBlock(_block, "Uncle is brother");
cwarn << " Uncle number: " << uncle.number;
cwarn << " Uncle parent number: " << uncleParent.number;
cwarn << " Block number: " << m_currentBlock.number;
UncleIsBrother ex;
ex << errinfo_uncleNumber(uncle.number);
ex << errinfo_currentNumber(m_currentBlock.number);
BOOST_THROW_EXCEPTION(ex);
}
uncle.verifyParent(uncleParent);
// tdIncrease += uncle.difficulty;
rewarded.push_back(uncle);
++ii;
}
else if (uncle.number == m_currentBlock.number)
catch (Exception& ex)
{
badBlock(_block, "Uncle is brother");
cwarn << " Uncle number: " << uncle.number;
cwarn << " Uncle parent number: " << uncleParent.number;
cwarn << " Block number: " << m_currentBlock.number;
BOOST_THROW_EXCEPTION(UncleIsBrother());
ex << errinfo_uncleIndex(ii);
throw;
}
uncle.verifyParent(uncleParent);
// tdIncrease += uncle.difficulty;
rewarded.push_back(uncle);
}
applyRewards(rewarded);
@ -731,15 +781,8 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
if (m_currentBlock.stateRoot != m_previousBlock.stateRoot && m_currentBlock.stateRoot != rootHash())
{
badBlock(_block, "Bad state root");
cnote << " Given to be:" << m_currentBlock.stateRoot;
// TODO: Fix
// cnote << SecureTrieDB<Address, OverlayDB>(&m_db, m_currentBlock.stateRoot);
cnote << " Calculated to be:" << rootHash();
cwarn << " VMTrace:\n" << vmTrace(_block, _bc, _ir);
// cnote << m_state;
// Rollback the trie.
m_db.rollback();
BOOST_THROW_EXCEPTION(InvalidStateRoot());
BOOST_THROW_EXCEPTION(InvalidStateRoot() << Hash256RequirementError(rootHash(), m_currentBlock.stateRoot));
}
if (m_currentBlock.gasUsed != gasUsed())
@ -1188,8 +1231,10 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per
if (!e.execute())
#if ETH_VMTRACE
{
(void)_onOp;
e.go(e.simpleTrace());
if (isChannelVisible<VMTraceChannel>())
e.go(e.simpleTrace());
else
e.go(_onOp);
}
#else
e.go(_onOp);

28
libethereum/State.h

@ -46,6 +46,22 @@ namespace test { class ImportTest; class StateLoader; }
namespace eth
{
// Import-specific errinfos
using errinfo_uncleIndex = boost::error_info<struct tag_uncleIndex, unsigned>;
using errinfo_currentNumber = boost::error_info<struct tag_currentNumber, u256>;
using errinfo_uncleNumber = boost::error_info<struct tag_uncleNumber, u256>;
using errinfo_unclesExcluded = boost::error_info<struct tag_unclesExcluded, h256Hash>;
using errinfo_block = boost::error_info<struct tag_block, bytes>;
using errinfo_now = boost::error_info<struct tag_now, unsigned>;
using errinfo_transactionIndex = boost::error_info<struct tag_transactionIndex, unsigned>;
using errinfo_vmtrace = boost::error_info<struct tag_vmtrace, std::string>;
using errinfo_receipts = boost::error_info<struct tag_receipts, std::vector<bytes>>;
using errinfo_required_LogBloom = boost::error_info<struct tag_required_LogBloom, LogBloom>;
using errinfo_got_LogBloom = boost::error_info<struct tag_get_LogBloom, LogBloom>;
using LogBloomRequirementError = boost::tuple<errinfo_required_LogBloom, errinfo_got_LogBloom>;
class BlockChain;
class State;
@ -294,10 +310,12 @@ public:
State fromPending(unsigned _i) const;
/// @returns the StateDiff caused by the pending transaction of index @a _i.
StateDiff pendingDiff(unsigned _i) const { return fromPending(_i).diff(fromPending(_i + 1)); }
StateDiff pendingDiff(unsigned _i) const { return fromPending(_i).diff(fromPending(_i + 1), true); }
/// @return the difference between this state (origin) and @a _c (destination).
StateDiff diff(State const& _c) const;
/// @param _quick if true doesn't check all addresses possible (/very/ slow for a full chain)
/// but rather only those touched by the transactions in creating the two States.
StateDiff diff(State const& _c, bool _quick = false) const;
/// Sync our state with the block chain.
/// This basically involves wiping ourselves if we've been superceded and rebuilding from the transaction queue.
@ -371,6 +389,7 @@ private:
TransactionReceipts m_receipts; ///< The corresponding list of transaction receipts.
h256Hash m_transactionSet; ///< The set of transaction hashes that we've included in the state.
OverlayDB m_lastTx;
AddressHash m_touched; ///< Tracks all addresses touched by transactions so far.
mutable std::unordered_map<Address, Account> m_cache; ///< Our address cache. This stores the states of each address that has (or at least might have) been changed.
@ -394,8 +413,9 @@ private:
std::ostream& operator<<(std::ostream& _out, State const& _s);
template <class DB>
void commit(std::unordered_map<Address, Account> const& _cache, DB& _db, SecureTrieDB<Address, DB>& _state)
AddressHash commit(std::unordered_map<Address, Account> const& _cache, DB& _db, SecureTrieDB<Address, DB>& _state)
{
AddressHash ret;
for (auto const& i: _cache)
if (i.second.isDirty())
{
@ -434,7 +454,9 @@ void commit(std::unordered_map<Address, Account> const& _cache, DB& _db, SecureT
_state.insert(i.first, &s.out());
}
ret.insert(i.first);
}
return ret;
}
}

43
libethereum/Transaction.cpp

@ -60,8 +60,25 @@ std::string badTransaction(bytesConstRef _tx, string const& _err)
return ret.str();
}
TransactionException dev::eth::toTransactionException(VMException const& _e)
TransactionException dev::eth::toTransactionException(Exception const& _e)
{
// Basic Transaction exceptions
if (!!dynamic_cast<BadRLP const*>(&_e))
return TransactionException::BadRLP;
if (!!dynamic_cast<OutOfGasIntrinsic const*>(&_e))
return TransactionException::OutOfGasIntrinsic;
if (!!dynamic_cast<InvalidSignature const*>(&_e))
return TransactionException::InvalidSignature;
// Executive exceptions
if (!!dynamic_cast<OutOfGasBase const*>(&_e))
return TransactionException::OutOfGasBase;
if (!!dynamic_cast<InvalidNonce const*>(&_e))
return TransactionException::InvalidNonce;
if (!!dynamic_cast<NotEnoughCash const*>(&_e))
return TransactionException::NotEnoughCash;
if (!!dynamic_cast<BlockGasLimitReached const*>(&_e))
return TransactionException::BlockGasLimitReached;
// VM execution exceptions
if (!!dynamic_cast<BadInstruction const*>(&_e))
return TransactionException::BadInstruction;
if (!!dynamic_cast<BadJumpDestination const*>(&_e))
@ -75,6 +92,28 @@ TransactionException dev::eth::toTransactionException(VMException const& _e)
return TransactionException::Unknown;
}
std::ostream& dev::eth::operator<<(std::ostream& _out, TransactionException const& _er)
{
switch (_er)
{
case TransactionException::None: _out << "None"; break;
case TransactionException::BadRLP: _out << "BadRLP"; break;
case TransactionException::OutOfGasIntrinsic: _out << "OutOfGasIntrinsic"; break;
case TransactionException::InvalidSignature: _out << "InvalidSignature"; break;
case TransactionException::InvalidNonce: _out << "InvalidNonce"; break;
case TransactionException::NotEnoughCash: _out << "NotEnoughCash"; break;
case TransactionException::OutOfGasBase: _out << "OutOfGasBase"; break;
case TransactionException::BlockGasLimitReached: _out << "BlockGasLimitReached"; break;
case TransactionException::BadInstruction: _out << "BadInstruction"; break;
case TransactionException::BadJumpDestination: _out << "BadJumpDestination"; break;
case TransactionException::OutOfGas: _out << "OutOfGas"; break;
case TransactionException::OutOfStack: _out << "OutOfStack"; break;
case TransactionException::StackUnderflow: _out << "StackUnderflow"; break;
default: _out << "Unknown"; break;
}
return _out;
}
Transaction::Transaction(bytesConstRef _rlpData, CheckTransaction _checkSig)
{
int field = 0;
@ -114,7 +153,7 @@ Transaction::Transaction(bytesConstRef _rlpData, CheckTransaction _checkSig)
throw;
}
if (_checkSig >= CheckTransaction::Cheap && !checkPayment())
BOOST_THROW_EXCEPTION(OutOfGasBase() << RequirementError(gasRequired(), (bigint)gas()));
BOOST_THROW_EXCEPTION(OutOfGasIntrinsic() << RequirementError(gasRequired(), (bigint)gas()));
}
Address const& Transaction::safeSender() const noexcept

6
libethereum/Transaction.h

@ -25,6 +25,7 @@
#include <libdevcore/SHA3.h>
#include <libethcore/Common.h>
#include <libevmcore/Params.h>
namespace dev
{
namespace eth
@ -48,6 +49,8 @@ enum class TransactionException
{
None = 0,
Unknown,
BadRLP,
OutOfGasIntrinsic, ///< Too little gas to pay for the base transaction cost.
InvalidSignature,
InvalidNonce,
NotEnoughCash,
@ -69,7 +72,8 @@ enum class CodeDeposit
struct VMException;
TransactionException toTransactionException(VMException const& _e);
TransactionException toTransactionException(Exception const& _e);
std::ostream& operator<<(std::ostream& _out, TransactionException const& _er);
/// Description of the result of executing a transaction.
struct ExecutionResult

322
libevm/VM.cpp

@ -45,165 +45,169 @@ static array<InstructionMetric, 256> metrics()
return s_ret;
}
bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
void VM::checkRequirements(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp, Instruction _inst)
{
// Reset leftovers from possible previous run
m_curPC = 0;
m_jumpDests.clear();
static const auto c_metrics = metrics();
auto& metric = c_metrics[static_cast<size_t>(_inst)];
m_stack.reserve((unsigned)c_stackLimit);
if (metric.gasPriceTier == InvalidTier)
BOOST_THROW_EXCEPTION(BadInstruction());
unique_ptr<CallParameters> callParams;
// FEES...
bigint runGas = c_tierStepGas[metric.gasPriceTier];
bigint newTempSize = m_temp.size();
bigint copySize = 0;
static const array<InstructionMetric, 256> c_metrics = metrics();
// should work, but just seems to result in immediate errorless exit on initial execution. yeah. weird.
//m_onFail = std::function<void()>(onOperation);
auto memNeed = [](u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; };
auto gasForMem = [](bigint _size) -> bigint
require(metric.args, metric.ret);
auto onOperation = [&]()
{
bigint s = _size / 32;
return (bigint)c_memoryGas * s + s * s / c_quadCoeffDiv;
if (_onOp)
_onOp(m_steps, _inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, io_gas, this, &_ext);
};
if (m_jumpDests.empty())
for (unsigned i = 0; i < _ext.code.size(); ++i)
auto memNeed = [](u256 _offset, dev::u256 _size) { return _size ? (bigint)_offset + _size : (bigint)0; };
switch (_inst)
{
case Instruction::SSTORE:
if (!_ext.store(m_stack.back()) && m_stack[m_stack.size() - 2])
runGas = c_sstoreSetGas;
else if (_ext.store(m_stack.back()) && !m_stack[m_stack.size() - 2])
{
if (_ext.code[i] == (byte)Instruction::JUMPDEST)
m_jumpDests.push_back(i);
else if (_ext.code[i] >= (byte)Instruction::PUSH1 && _ext.code[i] <= (byte)Instruction::PUSH32)
i += _ext.code[i] - (unsigned)Instruction::PUSH1 + 1;
runGas = c_sstoreResetGas;
_ext.sub.refunds += c_sstoreRefundGas;
}
u256 nextPC = m_curPC + 1;
for (uint64_t steps = 0; true; m_curPC = nextPC, nextPC = m_curPC + 1, ++steps)
else
runGas = c_sstoreResetGas;
break;
case Instruction::SLOAD:
runGas = c_sloadGas;
break;
// These all operate on memory and therefore potentially expand it:
case Instruction::MSTORE:
newTempSize = (bigint)m_stack.back() + 32;
break;
case Instruction::MSTORE8:
newTempSize = (bigint)m_stack.back() + 1;
break;
case Instruction::MLOAD:
newTempSize = (bigint)m_stack.back() + 32;
break;
case Instruction::RETURN:
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]);
break;
case Instruction::SHA3:
runGas = c_sha3Gas + (m_stack[m_stack.size() - 2] + 31) / 32 * c_sha3WordGas;
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]);
break;
case Instruction::CALLDATACOPY:
copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break;
case Instruction::CODECOPY:
copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break;
case Instruction::EXTCODECOPY:
copySize = m_stack[m_stack.size() - 4];
newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 4]);
break;
case Instruction::JUMPDEST:
runGas = 1;
break;
case Instruction::LOG0:
case Instruction::LOG1:
case Instruction::LOG2:
case Instruction::LOG3:
case Instruction::LOG4:
{
// INSTRUCTION...
Instruction inst = (Instruction)_ext.getCode(m_curPC);
auto metric = c_metrics[(int)inst];
int gasPriceTier = metric.gasPriceTier;
if (gasPriceTier == InvalidTier)
BOOST_THROW_EXCEPTION(BadInstruction());
// FEES...
bigint runGas = c_tierStepGas[metric.gasPriceTier];
bigint newTempSize = m_temp.size();
bigint copySize = 0;
// should work, but just seems to result in immediate errorless exit on initial execution. yeah. weird.
//m_onFail = std::function<void()>(onOperation);
require(metric.args, metric.ret);
auto onOperation = [&]()
{
if (_onOp)
_onOp(steps, inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, io_gas, this, &_ext);
};
switch (inst)
{
case Instruction::SSTORE:
if (!_ext.store(m_stack.back()) && m_stack[m_stack.size() - 2])
runGas = c_sstoreSetGas;
else if (_ext.store(m_stack.back()) && !m_stack[m_stack.size() - 2])
{
runGas = c_sstoreResetGas;
_ext.sub.refunds += c_sstoreRefundGas;
}
else
runGas = c_sstoreResetGas;
break;
unsigned n = (unsigned)_inst - (unsigned)Instruction::LOG0;
runGas = c_logGas + c_logTopicGas * n + (bigint)c_logDataGas * m_stack[m_stack.size() - 2];
newTempSize = memNeed(m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]);
break;
}
case Instruction::SLOAD:
runGas = c_sloadGas;
break;
case Instruction::CALL:
case Instruction::CALLCODE:
runGas = (bigint)c_callGas + m_stack[m_stack.size() - 1];
if (_inst != Instruction::CALLCODE && !_ext.exists(asAddress(m_stack[m_stack.size() - 2])))
runGas += c_callNewAccountGas;
if (m_stack[m_stack.size() - 3] > 0)
runGas += c_callValueTransferGas;
newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]));
break;
case Instruction::CREATE:
{
newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3]);
runGas = c_createGas;
break;
}
case Instruction::EXP:
{
auto expon = m_stack[m_stack.size() - 2];
runGas = c_expGas + c_expByteGas * (32 - (h256(expon).firstBitSet() / 8));
break;
}
default:;
}
// These all operate on memory and therefore potentially expand it:
case Instruction::MSTORE:
newTempSize = (bigint)m_stack.back() + 32;
break;
case Instruction::MSTORE8:
newTempSize = (bigint)m_stack.back() + 1;
break;
case Instruction::MLOAD:
newTempSize = (bigint)m_stack.back() + 32;
break;
case Instruction::RETURN:
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]);
break;
case Instruction::SHA3:
runGas = c_sha3Gas + (m_stack[m_stack.size() - 2] + 31) / 32 * c_sha3WordGas;
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 2]);
break;
case Instruction::CALLDATACOPY:
copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break;
case Instruction::CODECOPY:
copySize = m_stack[m_stack.size() - 3];
newTempSize = memNeed(m_stack.back(), m_stack[m_stack.size() - 3]);
break;
case Instruction::EXTCODECOPY:
copySize = m_stack[m_stack.size() - 4];
newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 4]);
break;
auto gasForMem = [](bigint _size) -> bigint
{
bigint s = _size / 32;
return (bigint)c_memoryGas * s + s * s / c_quadCoeffDiv;
};
case Instruction::JUMPDEST:
runGas = 1;
break;
newTempSize = (newTempSize + 31) / 32 * 32;
if (newTempSize > m_temp.size())
runGas += gasForMem(newTempSize) - gasForMem(m_temp.size());
runGas += c_copyGas * ((copySize + 31) / 32);
case Instruction::LOG0:
case Instruction::LOG1:
case Instruction::LOG2:
case Instruction::LOG3:
case Instruction::LOG4:
{
unsigned n = (unsigned)inst - (unsigned)Instruction::LOG0;
runGas = c_logGas + c_logTopicGas * n + (bigint)c_logDataGas * m_stack[m_stack.size() - 2];
newTempSize = memNeed(m_stack[m_stack.size() - 1], m_stack[m_stack.size() - 2]);
break;
}
onOperation();
case Instruction::CALL:
case Instruction::CALLCODE:
runGas = (bigint)c_callGas + m_stack[m_stack.size() - 1];
if (inst != Instruction::CALLCODE && !_ext.exists(asAddress(m_stack[m_stack.size() - 2])))
runGas += c_callNewAccountGas;
if (m_stack[m_stack.size() - 3] > 0)
runGas += c_callValueTransferGas;
newTempSize = std::max(memNeed(m_stack[m_stack.size() - 6], m_stack[m_stack.size() - 7]), memNeed(m_stack[m_stack.size() - 4], m_stack[m_stack.size() - 5]));
break;
if (io_gas < runGas)
BOOST_THROW_EXCEPTION(OutOfGas());
case Instruction::CREATE:
{
newTempSize = memNeed(m_stack[m_stack.size() - 2], m_stack[m_stack.size() - 3]);
runGas = c_createGas;
break;
}
case Instruction::EXP:
{
auto expon = m_stack[m_stack.size() - 2];
runGas = c_expGas + c_expByteGas * (32 - (h256(expon).firstBitSet() / 8));
break;
}
default:;
}
io_gas -= (u256)runGas;
newTempSize = (newTempSize + 31) / 32 * 32;
if (newTempSize > m_temp.size())
runGas += gasForMem(newTempSize) - gasForMem(m_temp.size());
runGas += c_copyGas * ((copySize + 31) / 32);
if (newTempSize > m_temp.size())
m_temp.resize((size_t)newTempSize);
}
onOperation();
bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
{
m_stack.reserve((unsigned)c_stackLimit);
if (io_gas < runGas)
BOOST_THROW_EXCEPTION(OutOfGas());
for (size_t i = 0; i < _ext.code.size(); ++i)
{
if (_ext.code[i] == (byte)Instruction::JUMPDEST)
m_jumpDests.push_back(i);
else if (_ext.code[i] >= (byte)Instruction::PUSH1 && _ext.code[i] <= (byte)Instruction::PUSH32)
i += _ext.code[i] - (size_t)Instruction::PUSH1 + 1;
}
io_gas -= (u256)runGas;
auto verifyJumpDest = [](u256 const& _dest, std::vector<uint64_t> const& _validDests)
{
auto nextPC = static_cast<uint64_t>(_dest);
if (!std::binary_search(_validDests.begin(), _validDests.end(), nextPC) || _dest > std::numeric_limits<uint64_t>::max())
BOOST_THROW_EXCEPTION(BadJumpDestination());
return nextPC;
};
if (newTempSize > m_temp.size())
m_temp.resize((size_t)newTempSize);
m_steps = 0;
for (auto nextPC = m_curPC + 1; true; m_curPC = nextPC, nextPC = m_curPC + 1, ++m_steps)
{
Instruction inst = (Instruction)_ext.getCode(m_curPC);
checkRequirements(io_gas, _ext, _onOp, inst);
// EXECUTE...
switch (inst)
{
case Instruction::ADD:
@ -299,7 +303,7 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
case Instruction::SIGNEXTEND:
if (m_stack.back() < 31)
{
unsigned const testBit(m_stack.back() * 8 + 7);
auto testBit = static_cast<unsigned>(m_stack.back()) * 8 + 7;
u256& number = m_stack[m_stack.size() - 2];
u256 mask = ((u256(1) << testBit) - 1);
if (boost::multiprecision::bit_test(number, testBit))
@ -480,7 +484,7 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
case Instruction::DUP15:
case Instruction::DUP16:
{
auto n = 1 + (int)inst - (int)Instruction::DUP1;
auto n = 1 + (unsigned)inst - (unsigned)Instruction::DUP1;
m_stack.push_back(m_stack[m_stack.size() - n]);
break;
}
@ -501,7 +505,7 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
case Instruction::SWAP15:
case Instruction::SWAP16:
{
unsigned n = (int)inst - (int)Instruction::SWAP1 + 2;
auto n = (unsigned)inst - (unsigned)Instruction::SWAP1 + 2;
auto d = m_stack.back();
m_stack.back() = m_stack[m_stack.size() - n];
m_stack[m_stack.size() - n] = d;
@ -535,18 +539,12 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
m_stack.pop_back();
break;
case Instruction::JUMP:
nextPC = m_stack.back();
if (find(m_jumpDests.begin(), m_jumpDests.end(), (uint64_t)nextPC) == m_jumpDests.end() || nextPC > numeric_limits<uint64_t>::max() )
BOOST_THROW_EXCEPTION(BadJumpDestination());
nextPC = verifyJumpDest(m_stack.back(), m_jumpDests);
m_stack.pop_back();
break;
case Instruction::JUMPI:
if (m_stack[m_stack.size() - 2])
{
nextPC = m_stack.back();
if (find(m_jumpDests.begin(), m_jumpDests.end(), (uint64_t)nextPC) == m_jumpDests.end() || nextPC > numeric_limits<uint64_t>::max() )
BOOST_THROW_EXCEPTION(BadJumpDestination());
}
nextPC = verifyJumpDest(m_stack.back(), m_jumpDests);
m_stack.pop_back();
m_stack.pop_back();
break;
@ -598,7 +596,7 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
break;
case Instruction::CREATE:
{
u256 endowment = m_stack.back();
auto endowment = m_stack.back();
m_stack.pop_back();
unsigned initOff = (unsigned)m_stack.back();
m_stack.pop_back();
@ -614,16 +612,14 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
case Instruction::CALL:
case Instruction::CALLCODE:
{
if (!callParams)
callParams.reset(new CallParameters);
callParams->gas = m_stack.back();
CallParameters callParams;
callParams.gas = m_stack.back();
if (m_stack[m_stack.size() - 3] > 0)
callParams->gas += c_callStipend;
callParams.gas += c_callStipend;
m_stack.pop_back();
callParams->codeAddress = asAddress(m_stack.back());
callParams.codeAddress = asAddress(m_stack.back());
m_stack.pop_back();
callParams->value = m_stack.back();
callParams.value = m_stack.back();
m_stack.pop_back();
unsigned inOff = (unsigned)m_stack.back();
@ -635,19 +631,19 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
unsigned outSize = (unsigned)m_stack.back();
m_stack.pop_back();
if (_ext.balance(_ext.myAddress) >= callParams->value && _ext.depth < 1024)
if (_ext.balance(_ext.myAddress) >= callParams.value && _ext.depth < 1024)
{
callParams->onOp = _onOp;
callParams->senderAddress = _ext.myAddress;
callParams->receiveAddress = inst == Instruction::CALL ? callParams->codeAddress : callParams->senderAddress;
callParams->data = bytesConstRef(m_temp.data() + inOff, inSize);
callParams->out = bytesRef(m_temp.data() + outOff, outSize);
m_stack.push_back(_ext.call(*callParams));
callParams.onOp = _onOp;
callParams.senderAddress = _ext.myAddress;
callParams.receiveAddress = inst == Instruction::CALL ? callParams.codeAddress : callParams.senderAddress;
callParams.data = bytesConstRef(m_temp.data() + inOff, inSize);
callParams.out = bytesRef(m_temp.data() + outOff, outSize);
m_stack.push_back(_ext.call(callParams));
}
else
m_stack.push_back(0);
io_gas += callParams->gas;
io_gas += callParams.gas;
break;
}
case Instruction::RETURN:

6
libevm/VM.h

@ -54,16 +54,18 @@ class VM: public VMFace
public:
virtual bytesConstRef execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp) override final;
u256 curPC() const { return m_curPC; }
uint64_t curPC() const { return m_curPC; }
bytes const& memory() const { return m_temp; }
u256s const& stack() const { return m_stack; }
private:
void checkRequirements(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp, Instruction _inst);
void require(u256 _n, u256 _d) { if (m_stack.size() < _n) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(StackUnderflow() << RequirementError((bigint)_n, (bigint)m_stack.size())); } if (m_stack.size() - _n + _d > c_stackLimit) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(OutOfStack() << RequirementError((bigint)(_d - _n), (bigint)m_stack.size())); } }
void requireMem(unsigned _n) { if (m_temp.size() < _n) { m_temp.resize(_n); } }
u256 m_curPC = 0;
uint64_t m_curPC = 0;
uint64_t m_steps = 0;
bytes m_temp;
u256s m_stack;
std::vector<uint64_t> m_jumpDests;

1
libevm/VMFace.h

@ -25,6 +25,7 @@ namespace dev
namespace eth
{
#define ETH_SIMPLE_EXCEPTION_VM(X) struct X: virtual VMException { public X(): VMException(#X) {} };
struct VMException: virtual Exception {};
struct BreakPointHit: virtual VMException {};
struct BadInstruction: virtual VMException {};

2
libevmasm/Assembly.cpp

@ -109,7 +109,7 @@ string Assembly::getLocationFromSources(StringMap const& _sourceCodes, SourceLoc
if (newLinePos != string::npos)
cut = cut.substr(0, newLinePos) + "...";
return move(cut);
return cut;
}
ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap const& _sourceCodes) const

4
libevmcore/Exceptions.h

@ -28,8 +28,8 @@ namespace dev
namespace eth
{
struct InvalidDeposit: virtual Exception {};
struct InvalidOpcode: virtual Exception {};
DEV_SIMPLE_EXCEPTION(InvalidDeposit);
DEV_SIMPLE_EXCEPTION(InvalidOpcode);
}
}

4
libp2p/Common.h

@ -183,8 +183,8 @@ struct NodeIPEndpoint
uint16_t udpPort = 0;
uint16_t tcpPort = 0;
operator bi::udp::endpoint() const { return std::move(bi::udp::endpoint(address, udpPort)); }
operator bi::tcp::endpoint() const { return std::move(bi::tcp::endpoint(address, tcpPort)); }
operator bi::udp::endpoint() const { return bi::udp::endpoint(address, udpPort); }
operator bi::tcp::endpoint() const { return bi::tcp::endpoint(address, tcpPort); }
operator bool() const { return !address.is_unspecified() && udpPort > 0 && tcpPort > 0; }

4
libp2p/Host.cpp

@ -834,7 +834,7 @@ KeyPair Host::networkAlias(bytesConstRef _b)
{
RLP r(_b);
if (r.itemCount() == 3 && r[0].isInt() && r[0].toInt<unsigned>() >= 3)
return move(KeyPair(move(Secret(r[1].toBytes()))));
return KeyPair(Secret(r[1].toBytes()));
else
return move(KeyPair::create());
return KeyPair::create();
}

2
libp2p/Network.cpp

@ -111,7 +111,7 @@ std::set<bi::address> Network::getInterfaceAddresses()
#endif
return std::move(addresses);
return addresses;
}
int Network::tcp4Listen(bi::tcp::acceptor& _acceptor, NetworkPreferences const& _netPrefs)

12
libp2p/NodeTable.cpp

@ -88,7 +88,7 @@ shared_ptr<NodeEntry> NodeTable::addNode(Node const& _node, NodeRelation _relati
}
if (!_node.endpoint)
return move(shared_ptr<NodeEntry>());
return shared_ptr<NodeEntry>();
// ping address to recover nodeid if nodeid is empty
if (!_node.id)
@ -98,7 +98,7 @@ shared_ptr<NodeEntry> NodeTable::addNode(Node const& _node, NodeRelation _relati
DEV_GUARDED(x_pubkDiscoverPings)
m_pubkDiscoverPings[_node.endpoint.address] = std::chrono::steady_clock::now();
ping(_node.endpoint);
return move(shared_ptr<NodeEntry>());
return shared_ptr<NodeEntry>();
}
DEV_GUARDED(x_nodes)
@ -129,7 +129,7 @@ list<NodeId> NodeTable::nodes() const
DEV_GUARDED(x_nodes)
for (auto& i: m_nodes)
nodes.push_back(i.second->id);
return move(nodes);
return nodes;
}
list<NodeEntry> NodeTable::snapshot() const
@ -140,7 +140,7 @@ list<NodeEntry> NodeTable::snapshot() const
for (auto const& np: s.nodes)
if (auto n = np.lock())
ret.push_back(*n);
return move(ret);
return ret;
}
Node NodeTable::node(NodeId const& _id)
@ -282,7 +282,7 @@ vector<shared_ptr<NodeEntry>> NodeTable::nearestNodeEntries(NodeId _target)
for (auto const& n: nodes.second)
if (ret.size() < s_bucketSize && !!n->endpoint && n->endpoint.isAllowed())
ret.push_back(n);
return move(ret);
return ret;
}
void NodeTable::ping(NodeIPEndpoint _to) const
@ -422,8 +422,8 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes
unsigned packetType = signedBytes[0];
bytesConstRef rlpBytes(_packet.cropped(h256::size + Signature::size + 1));
RLP rlp(rlpBytes);
try {
RLP rlp(rlpBytes);
switch (packetType)
{
case Pong::type:

4
libp2p/RLPxFrameIO.cpp

@ -154,7 +154,7 @@ h128 RLPXFrameIO::egressDigest()
SHA3_256 h(m_egressMac);
h128 digest;
h.TruncatedFinal(digest.data(), h128::size);
return move(digest);
return digest;
}
h128 RLPXFrameIO::ingressDigest()
@ -162,7 +162,7 @@ h128 RLPXFrameIO::ingressDigest()
SHA3_256 h(m_ingressMac);
h128 digest;
h.TruncatedFinal(digest.data(), h128::size);
return move(digest);
return digest;
}
void RLPXFrameIO::updateEgressMACWithHeader(bytesConstRef _headerCipher)

4
libp2p/UDP.cpp

@ -52,12 +52,12 @@ h256 RLPXDatagramFace::sign(Secret const& _k)
bytesConstRef signedRLPx(&data[h256::size], data.size() - h256::size);
dev::sha3(signedRLPx).ref().copyTo(rlpxHash);
return std::move(sighash);
return sighash;
}
Public RLPXDatagramFace::authenticate(bytesConstRef _sig, bytesConstRef _rlp)
{
Signature const& sig = *(Signature const*)_sig.data();
return std::move(dev::recover(sig, sha3(_rlp)));
return dev::recover(sig, sha3(_rlp));
}

2
libp2p/UDP.h

@ -81,7 +81,7 @@ template <class T>
struct RLPXDatagram: public RLPXDatagramFace
{
RLPXDatagram(bi::udp::endpoint const& _ep): RLPXDatagramFace(_ep) {}
static T fromBytesConstRef(bi::udp::endpoint const& _ep, bytesConstRef _bytes) { try { T t(_ep); t.interpretRLP(_bytes); return std::move(t); } catch(...) { T t(_ep); return std::move(t); } }
static T fromBytesConstRef(bi::udp::endpoint const& _ep, bytesConstRef _bytes) { try { T t(_ep); t.interpretRLP(_bytes); return t; } catch(...) { return T{_ep}; } }
uint8_t packetType() { return T::type; }
};

42
libsolidity/AST.cpp

@ -410,7 +410,14 @@ void InheritanceSpecifier::checkTypeRequirements()
BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for constructor call."));
for (size_t i = 0; i < m_arguments.size(); ++i)
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i]))
BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in constructer call."));
BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError(
"Invalid type for argument in constructor call. "
"Invalid implicit conversion from " +
m_arguments[i]->getType()->toString() +
" to " +
parameterTypes[i]->toString() +
" requested."
));
}
TypePointer StructDefinition::getType(ContractDefinition const*) const
@ -592,7 +599,14 @@ void ModifierInvocation::checkTypeRequirements(vector<ContractDefinition const*>
BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for modifier invocation."));
for (size_t i = 0; i < m_arguments.size(); ++i)
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*(*parameters)[i]->getType()))
BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in modifier invocation."));
BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError(
"Invalid type for argument in modifier invocation. "
"Invalid implicit conversion from " +
m_arguments[i]->getType()->toString() +
" to " +
(*parameters)[i]->getType()->toString() +
" requested."
));
}
void EventDefinition::checkTypeRequirements()
@ -782,9 +796,18 @@ void FunctionCall::checkTypeRequirements(TypePointers const*)
{
// call by positional arguments
for (size_t i = 0; i < m_arguments.size(); ++i)
if (!functionType->takesArbitraryParameters() &&
!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i]))
BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError("Invalid type for argument in function call."));
if (
!functionType->takesArbitraryParameters() &&
!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i])
)
BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError(
"Invalid type for argument in function call. "
"Invalid implicit conversion from " +
m_arguments[i]->getType()->toString() +
" to " +
parameterTypes[i]->toString() +
" requested."
));
}
else
{
@ -808,7 +831,14 @@ void FunctionCall::checkTypeRequirements(TypePointers const*)
if (parameterNames[j] == *m_names[i]) {
// check type convertible
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[j]))
BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call."));
BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError(
"Invalid type for argument in function call. "
"Invalid implicit conversion from " +
m_arguments[i]->getType()->toString() +
" to " +
parameterTypes[i]->toString() +
" requested."
));
found = true;
break;

2
libsolidity/AST.h

@ -503,7 +503,7 @@ public:
/// Returns the declared or inferred type. Can be an empty pointer if no type was explicitly
/// declared and there is no assignment to the variable that fixes the type.
TypePointer getType(ContractDefinition const* = nullptr) const { return m_type; }
TypePointer getType(ContractDefinition const* = nullptr) const override { return m_type; }
void setType(std::shared_ptr<Type const> const& _type) { m_type = _type; }
virtual bool isLValue() const override;

2
libsolidity/CompilerContext.cpp

@ -133,7 +133,7 @@ set<Declaration const*> CompilerContext::getFunctionsWithoutCode()
for (auto const& it: m_functionEntryLabels)
if (m_functionsWithCode.count(it.first) == 0)
functions.insert(it.first);
return move(functions);
return functions;
}
ModifierDefinition const& CompilerContext::getFunctionModifier(string const& _name) const

2
libsolidity/LValue.h

@ -109,7 +109,7 @@ public:
StorageItem(CompilerContext& _compilerContext, Declaration const& _declaration);
/// Constructs the LValue and assumes that the storage reference is already on the stack.
StorageItem(CompilerContext& _compilerContext, Type const& _type);
virtual unsigned sizeOnStack() const { return 2; }
virtual unsigned sizeOnStack() const override { return 2; }
virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const override;
virtual void storeValue(
Type const& _sourceType,

12
libsolidity/Types.cpp

@ -1459,29 +1459,29 @@ MagicType::MagicType(MagicType::Kind _kind):
switch (m_kind)
{
case Kind::Block:
m_members = move(MemberList({
m_members = MemberList({
{"coinbase", make_shared<IntegerType>(0, IntegerType::Modifier::Address)},
{"timestamp", make_shared<IntegerType>(256)},
{"blockhash", make_shared<FunctionType>(strings{"uint"}, strings{"bytes32"}, FunctionType::Location::BlockHash)},
{"difficulty", make_shared<IntegerType>(256)},
{"number", make_shared<IntegerType>(256)},
{"gaslimit", make_shared<IntegerType>(256)}
}));
});
break;
case Kind::Message:
m_members = move(MemberList({
m_members = MemberList({
{"sender", make_shared<IntegerType>(0, IntegerType::Modifier::Address)},
{"gas", make_shared<IntegerType>(256)},
{"value", make_shared<IntegerType>(256)},
{"data", make_shared<ArrayType>(ReferenceType::Location::CallData)},
{"sig", make_shared<FixedBytesType>(4)}
}));
});
break;
case Kind::Transaction:
m_members = move(MemberList({
m_members = MemberList({
{"origin", make_shared<IntegerType>(0, IntegerType::Modifier::Address)},
{"gasprice", make_shared<IntegerType>(256)}
}));
});
break;
default:
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown kind of magic."));

4
libsolidity/Types.h

@ -407,7 +407,7 @@ public:
virtual TypePointer unaryOperatorResult(Token::Value _operator) const override;
virtual bool operator==(const Type& _other) const override;
virtual unsigned getCalldataEncodedSize(bool _padded) const override;
virtual bool isDynamicallySized() const { return m_hasDynamicLength; }
virtual bool isDynamicallySized() const override { return m_hasDynamicLength; }
virtual u256 getStorageSize() const override;
virtual unsigned getSizeOnStack() const override;
virtual std::string toString() const override;
@ -820,7 +820,7 @@ public:
return TypePointer();
}
virtual bool operator==(Type const& _other) const;
virtual bool operator==(Type const& _other) const override;
virtual bool canBeStored() const override { return false; }
virtual bool canLiveOutsideStorage() const override { return true; }
virtual unsigned getSizeOnStack() const override { return 0; }

2
libtestutils/FixedClient.h

@ -48,7 +48,7 @@ public:
virtual eth::State asOf(h256 const& _h) const override;
virtual eth::State preMine() const override { ReadGuard l(x_stateDB); return m_state; }
virtual eth::State postMine() const override { ReadGuard l(x_stateDB); return m_state; }
virtual void setAddress(Address _us) { WriteGuard l(x_stateDB); m_state.setAddress(_us); }
virtual void setAddress(Address _us) override { WriteGuard l(x_stateDB); m_state.setAddress(_us); }
virtual void prepareForTransaction() override {}
private:

2
libweb3jsonrpc/WebThreeStubServer.h

@ -43,7 +43,7 @@ class WebThreeStubServer: public dev::WebThreeStubServerBase, public dev::WebThr
public:
WebThreeStubServer(jsonrpc::AbstractServerConnector& _conn, dev::WebThreeDirect& _web3, std::shared_ptr<dev::eth::AccountHolder> const& _ethAccounts, std::vector<dev::KeyPair> const& _shhAccounts);
virtual std::string web3_clientVersion();
virtual std::string web3_clientVersion() override;
private:
virtual dev::eth::Interface* client() override;

18
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -781,17 +781,15 @@ string WebThreeStubServerBase::eth_newFilter(Json::Value const& _json)
}
}
string WebThreeStubServerBase::eth_newBlockFilter(string const& _filter)
string WebThreeStubServerBase::eth_newBlockFilter()
{
h256 filter;
if (_filter.compare("chain") == 0 || _filter.compare("latest") == 0)
filter = dev::eth::ChainChangedFilter;
else if (_filter.compare("pending") == 0)
filter = dev::eth::PendingChangedFilter;
else
BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
h256 filter = dev::eth::ChainChangedFilter;
return toJS(client()->installWatch(filter));
}
string WebThreeStubServerBase::eth_newPendingTransactionFilter()
{
h256 filter = dev::eth::PendingChangedFilter;
return toJS(client()->installWatch(filter));
}

3
libweb3jsonrpc/WebThreeStubServerBase.h

@ -107,7 +107,8 @@ public:
virtual std::string eth_compileSerpent(std::string const& _s);
virtual std::string eth_compileSolidity(std::string const& _code);
virtual std::string eth_newFilter(Json::Value const& _json);
virtual std::string eth_newBlockFilter(std::string const& _filter);
virtual std::string eth_newBlockFilter();
virtual std::string eth_newPendingTransactionFilter();
virtual bool eth_uninstallFilter(std::string const& _filterId);
virtual Json::Value eth_getFilterChanges(std::string const& _filterId);
virtual Json::Value eth_getFilterLogs(std::string const& _filterId);

14
libweb3jsonrpc/abstractwebthreestubserver.h

@ -47,7 +47,8 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
this->bindAndAddMethod(jsonrpc::Procedure("eth_compileSerpent", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_compileSerpentI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_compileSolidity", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_compileSolidityI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_newFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_newFilterI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_newBlockFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_newBlockFilterI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_newBlockFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_newBlockFilterI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_newPendingTransactionFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_newPendingTransactionFilterI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_uninstallFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_uninstallFilterI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_getFilterChanges", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getFilterChangesI);
this->bindAndAddMethod(jsonrpc::Procedure("eth_getFilterLogs", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_getFilterLogsI);
@ -228,7 +229,13 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
}
inline virtual void eth_newBlockFilterI(const Json::Value &request, Json::Value &response)
{
response = this->eth_newBlockFilter(request[0u].asString());
(void)request;
response = this->eth_newBlockFilter();
}
inline virtual void eth_newPendingTransactionFilterI(const Json::Value &request, Json::Value &response)
{
(void)request;
response = this->eth_newPendingTransactionFilter();
}
inline virtual void eth_uninstallFilterI(const Json::Value &request, Json::Value &response)
{
@ -359,7 +366,8 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer<AbstractWebThr
virtual std::string eth_compileSerpent(const std::string& param1) = 0;
virtual std::string eth_compileSolidity(const std::string& param1) = 0;
virtual std::string eth_newFilter(const Json::Value& param1) = 0;
virtual std::string eth_newBlockFilter(const std::string& param1) = 0;
virtual std::string eth_newBlockFilter() = 0;
virtual std::string eth_newPendingTransactionFilter() = 0;
virtual bool eth_uninstallFilter(const std::string& param1) = 0;
virtual Json::Value eth_getFilterChanges(const std::string& param1) = 0;
virtual Json::Value eth_getFilterLogs(const std::string& param1) = 0;

3
libweb3jsonrpc/spec.json

@ -36,7 +36,8 @@
{ "name": "eth_compileSerpent", "params": [""], "order": [], "returns": ""},
{ "name": "eth_compileSolidity", "params": [""], "order": [], "returns": ""},
{ "name": "eth_newFilter", "params": [{}], "order": [], "returns": ""},
{ "name": "eth_newBlockFilter", "params": [""], "order": [], "returns": ""},
{ "name": "eth_newBlockFilter", "params": [], "order": [], "returns": ""},
{ "name": "eth_newPendingTransactionFilter", "params": [], "order": [], "returns": ""},
{ "name": "eth_uninstallFilter", "params": [""], "order": [], "returns": true},
{ "name": "eth_getFilterChanges", "params": [""], "order": [], "returns": []},
{ "name": "eth_getFilterLogs", "params": [""], "order": [], "returns": []},

8
libwhisper/WhisperHost.h

@ -54,7 +54,7 @@ public:
virtual void inject(Envelope const& _e, WhisperPeer* _from = nullptr) override;
virtual Topics const& fullTopics(unsigned _id) const { try { return m_filters.at(m_watches.at(_id).id).full; } catch (...) { return EmptyTopics; } }
virtual Topics const& fullTopics(unsigned _id) const override { try { return m_filters.at(m_watches.at(_id).id).full; } catch (...) { return EmptyTopics; } }
virtual unsigned installWatch(Topics const& _filter) override;
virtual unsigned installWatchOnId(h256 _filterId) override;
virtual void uninstallWatch(unsigned _watchId) override;
@ -69,11 +69,11 @@ public:
void cleanup();
protected:
void doWork();
virtual void doWork() override;
private:
virtual void onStarting() { startWorking(); }
virtual void onStopping() { stopWorking(); }
virtual void onStarting() override { startWorking(); }
virtual void onStopping() override { stopWorking(); }
void streamMessage(h256 _m, RLPStream& _s) const;

4
mix/ClientModel.cpp

@ -539,7 +539,9 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
// filter out locations that match whole function or contract
SourceLocation location = instruction.getLocation();
QString source = QString::fromUtf8(location.sourceName->c_str());
QString source;
if (location.sourceName)
source = QString::fromUtf8(location.sourceName->c_str());
if (m_codeModel->isContractOrFunctionLocation(location))
location = dev::SourceLocation(-1, -1, location.sourceName);

2
mix/CodeModel.cpp

@ -67,7 +67,7 @@ private:
return LocationPair(_node.getLocation().start, _node.getLocation().end);
}
virtual bool visit(FunctionDefinition const&)
virtual bool visit(FunctionDefinition const&) override
{
m_functionScope = true;
return true;

44
mix/MixClient.cpp

@ -203,27 +203,29 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c
switch (er.excepted)
{
case TransactionException::None:
break;
case TransactionException::NotEnoughCash:
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Insufficient balance for contract deployment"));
case TransactionException::OutOfGasBase:
case TransactionException::OutOfGas:
BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Not enough gas"));
case TransactionException::BlockGasLimitReached:
BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Block gas limit reached"));
case TransactionException::OutOfStack:
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Out of stack"));
case TransactionException::StackUnderflow:
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Stack underflow"));
//these should not happen in mix
case TransactionException::Unknown:
case TransactionException::BadInstruction:
case TransactionException::BadJumpDestination:
case TransactionException::InvalidSignature:
case TransactionException::InvalidNonce:
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Internal execution error"));
};
case TransactionException::None:
break;
case TransactionException::NotEnoughCash:
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Insufficient balance for contract deployment"));
case TransactionException::OutOfGasIntrinsic:
case TransactionException::OutOfGasBase:
case TransactionException::OutOfGas:
BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Not enough gas"));
case TransactionException::BlockGasLimitReached:
BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Block gas limit reached"));
case TransactionException::OutOfStack:
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Out of stack"));
case TransactionException::StackUnderflow:
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Stack underflow"));
//these should not happen in mix
case TransactionException::Unknown:
case TransactionException::BadInstruction:
case TransactionException::BadJumpDestination:
case TransactionException::InvalidSignature:
case TransactionException::InvalidNonce:
case TransactionException::BadRLP:
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Internal execution error"));
}
ExecutionResult d;
d.result = er;

2
mix/MixClient.h

@ -80,7 +80,7 @@ protected:
/// ClientBase methods
using ClientBase::asOf;
virtual dev::eth::State asOf(h256 const& _block) const override;
virtual dev::eth::BlockChain& bc() { return *m_bc; }
virtual dev::eth::BlockChain& bc() override { return *m_bc; }
virtual dev::eth::BlockChain const& bc() const override { return *m_bc; }
virtual dev::eth::State preMine() const override { ReadGuard l(x_state); return m_startState; }
virtual dev::eth::State postMine() const override { ReadGuard l(x_state); return m_state; }

BIN
mix/qml/img/addblock.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 801 B

BIN
mix/qml/img/addblock@2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
mix/qml/img/duplicateicon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1020 B

BIN
mix/qml/img/duplicateicon@2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
mix/qml/img/leftarrow.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

BIN
mix/qml/img/leftarrow@2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 947 B

BIN
mix/qml/img/newaccounticon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 B

BIN
mix/qml/img/newaccounticon@2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

BIN
mix/qml/img/recyclediscard.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

BIN
mix/qml/img/recyclediscard@2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
mix/qml/img/recycleicon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 B

BIN
mix/qml/img/recycleicon@2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
mix/qml/img/recyclekeep.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

BIN
mix/qml/img/recyclekeep@2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
mix/qml/img/restoreicon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save