Browse Source

Merge remote-tracking branch 'up/develop' into bugFix2

cl-refactor
yann300 10 years ago
parent
commit
a3c67eca97
  1. 23
      CMakeLists.txt
  2. 4
      alethzero/CMakeLists.txt
  3. 6
      alethzero/Main.ui
  4. 28
      alethzero/MainWin.cpp
  5. 1
      alethzero/MainWin.h
  6. 2
      alethzero/NatspecHandler.cpp
  7. 6
      alethzero/Transact.cpp
  8. 113
      eth/main.cpp
  9. 9
      exp/main.cpp
  10. 2
      libdevcore/Common.cpp
  11. 4
      libdevcore/CommonIO.h
  12. 37
      libdevcore/Log.cpp
  13. 140
      libdevcore/Log.h
  14. 6
      libdevcore/RLP.cpp
  15. 2
      libdevcore/RLP.h
  16. 148
      libdevcore/Terminal.h
  17. 13
      libdevcrypto/MemoryDB.cpp
  18. 4
      libdevcrypto/MemoryDB.h
  19. 2
      libdevcrypto/OverlayDB.cpp
  20. 2
      libdevcrypto/TrieDB.cpp
  21. 14
      libdevcrypto/TrieDB.h
  22. 21
      libethash-cl/ethash_cl_miner.cpp
  23. 2
      libethash-cl/ethash_cl_miner.h
  24. 2
      libethcore/Common.cpp
  25. 13
      libethcore/Ethash.cpp
  26. 14
      libethcore/Ethash.h
  27. 8
      libethcore/EthashAux.cpp
  28. 108
      libethereum/BlockChain.cpp
  29. 11
      libethereum/BlockChain.h
  30. 10
      libethereum/BlockQueue.cpp
  31. 2
      libethereum/BlockQueue.h
  32. 37
      libethereum/Client.cpp
  33. 8
      libethereum/Client.h
  34. 5
      libethereum/ClientBase.cpp
  35. 8
      libethereum/ClientBase.h
  36. 6
      libethereum/Executive.cpp
  37. 2
      libethereum/Executive.h
  38. 13
      libethereum/State.cpp
  39. 50
      libethereum/State.h
  40. 2
      libethereum/TransactionQueue.cpp
  41. 2
      libethereum/TransactionQueue.h
  42. 2
      libevmcore/Assembly.cpp
  43. 28
      libp2p/Common.cpp
  44. 22
      libp2p/Common.h
  45. 2
      libp2p/Network.cpp
  46. 22
      libp2p/NodeTable.cpp
  47. 26
      libp2p/NodeTable.h
  48. 8
      libp2p/RLPxHandshake.cpp
  49. 12
      libp2p/Session.cpp
  50. 258
      libsolidity/AST.cpp
  51. 72
      libsolidity/AST.h
  52. 6
      libsolidity/Compiler.cpp
  53. 38
      libsolidity/CompilerContext.cpp
  54. 11
      libsolidity/CompilerContext.h
  55. 40
      libsolidity/DeclarationContainer.cpp
  56. 8
      libsolidity/DeclarationContainer.h
  57. 47
      libsolidity/ExpressionCompiler.cpp
  58. 8
      libsolidity/LValue.cpp
  59. 123
      libsolidity/NameAndTypeResolver.cpp
  60. 25
      libsolidity/NameAndTypeResolver.h
  61. 125
      libsolidity/Types.cpp
  62. 70
      libsolidity/Types.h
  63. 8
      libtestutils/Common.cpp
  64. 3
      libtestutils/Common.h
  65. 4
      mix/CodeModel.cpp
  66. 2
      mix/MixClient.cpp
  67. 29
      mix/qml/CodeEditorView.qml
  68. 8
      mix/qml/WebCodeEditor.qml
  69. 2
      mix/qml/WebPreview.qml
  70. 1
      mix/qml/html/WebContainer.html
  71. 65
      mix/qml/html/cm/inkpot.css
  72. 3
      mix/qml/html/codeeditor.html
  73. 9
      mix/qml/html/codeeditor.js
  74. 1
      mix/web.qrc
  75. 2
      neth/main.cpp
  76. 60
      test/CMakeLists.txt
  77. 120
      test/JSON_test.sol
  78. 12
      test/TestHelper.cpp
  79. 3
      test/TestHelper.h
  80. 247
      test/bcJS_API_TestFiller.json
  81. 579
      test/bcRPC_API_TestFiller.json
  82. 0
      test/deprecated/fork.cpp
  83. 0
      test/deprecated/kademlia.cpp
  84. 0
      test/deprecated/main.cpp
  85. 0
      test/deprecated/txTest.cpp
  86. 31
      test/fuzzTesting/CMakeLists.txt
  87. 2
      test/fuzzTesting/checkRandomStateTest.cpp
  88. 3
      test/fuzzTesting/checkRandomVMTest.cpp
  89. 4
      test/fuzzTesting/createRandomStateTest.cpp
  90. 2
      test/fuzzTesting/createRandomVMTest.cpp
  91. 5
      test/libdevcore/CMakeLists.txt
  92. 4
      test/libdevcore/rlp.cpp
  93. 5
      test/libdevcrypto/CMakeLists.txt
  94. 0
      test/libdevcrypto/MemTrie.cpp
  95. 0
      test/libdevcrypto/MemTrie.h
  96. 0
      test/libdevcrypto/TrieHash.cpp
  97. 0
      test/libdevcrypto/TrieHash.h
  98. 0
      test/libdevcrypto/crypto.cpp
  99. 4
      test/libdevcrypto/hexPrefix.cpp
  100. 4
      test/libdevcrypto/trie.cpp

23
CMakeLists.txt

@ -1,10 +1,22 @@
# cmake global
cmake_minimum_required(VERSION 2.8.12)
project(ethereum)
set(CMAKE_AUTOMOC ON)
# link_directories interprate relative paths with respect to CMAKE_CURRENT_SOURCE_DIR
cmake_policy(SET CMP0015 NEW)
# let cmake autolink dependencies on windows
# it's specified globally, cause qt libraries requires that on windows and they are also found globally
cmake_policy(SET CMP0020 NEW)
project(ethereum)
# 3.1 and above
if ((${CMAKE_MAJOR_VERSION} GREATER 2) AND (${CMAKE_MINOR_VERSION} GREATER 0))
# implicitly dereference variables (deprecated in 3.1)
cmake_policy(SET CMP0054 NEW)
endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
@ -124,9 +136,6 @@ endfunction()
######################################################################################################
set(CMAKE_AUTOMOC ON)
cmake_policy(SET CMP0015 NEW)
# Clear invalid option
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
if (PARANOID)
@ -242,11 +251,11 @@ if ("x${CMAKE_BUILD_TYPE}" STREQUAL "x")
set(CMAKE_BUILD_TYPE "Release")
endif ()
# Default TARGET_PLATFORM to ${CMAKE_SYSTEM}
# Default TARGET_PLATFORM to ${CMAKE_SYSTEM_NAME}
# change this once we support cross compiling
set(TARGET_PLATFORM CACHE STRING ${CMAKE_SYSTEM})
set(TARGET_PLATFORM CACHE STRING ${CMAKE_SYSTEM_NAME})
if ("x${TARGET_PLATFORM}" STREQUAL "x")
set(TARGET_PLATFORM ${CMAKE_SYSTEM})
set(TARGET_PLATFORM ${CMAKE_SYSTEM_NAME})
endif ()
include(EthDependencies)

4
alethzero/CMakeLists.txt

@ -51,7 +51,9 @@ target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} secp256k1)
target_link_libraries(${EXECUTABLE} lll)
target_link_libraries(${EXECUTABLE} solidity)
if (SOLIDITY)
target_link_libraries(${EXECUTABLE} solidity)
endif ()
target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcore)
target_link_libraries(${EXECUTABLE} web3jsonrpc)

6
alethzero/Main.ui

@ -176,6 +176,7 @@
<addaction name="clearPending"/>
<addaction name="killBlockchain"/>
<addaction name="inject"/>
<addaction name="injectBlock"/>
<addaction name="forceMining"/>
<addaction name="separator"/>
<addaction name="usePrivate"/>
@ -1685,6 +1686,11 @@ font-size: 14pt</string>
<string>Retry Unknown Parent Blocks</string>
</property>
</action>
<action name="injectBlock">
<property name="text">
<string>In&amp;ject Block</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>

28
alethzero/MainWin.cpp

@ -116,6 +116,11 @@ QString contentsOfQResource(string const& res)
Address c_newConfig = Address("c6d9d2cd449a754c494264e1809c50e34d64562b");
//Address c_nameReg = Address("ddd1cea741d548f90d86fb87a3ae6492e18c03a1");
static QString filterOutTerminal(QString _s)
{
return _s.replace(QRegExp("\x1b\\[(\\d;)?\\d+m"), "");
}
Main::Main(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Main),
@ -130,7 +135,7 @@ Main::Main(QWidget *parent) :
{
simpleDebugOut(s, c);
m_logLock.lock();
m_logHistory.append(QString::fromStdString(s) + "\n");
m_logHistory.append(filterOutTerminal(QString::fromStdString(s)) + "\n");
m_logChanged = true;
m_logLock.unlock();
// ui->log->addItem(QString::fromStdString(s));
@ -164,7 +169,7 @@ Main::Main(QWidget *parent) :
statusBar()->addPermanentWidget(ui->chainStatus);
statusBar()->addPermanentWidget(ui->blockCount);
ui->blockCount->setText(QString("PV%2 D%3 %4-%5 v%6").arg(eth::c_protocolVersion).arg(c_databaseVersion).arg(QString::fromStdString(ProofOfWork::name())).arg(ProofOfWork::revision()).arg(dev::Version));
ui->blockCount->setText(QString("PV%1.%2 D%3 %4-%5 v%6").arg(eth::c_protocolVersion).arg(eth::c_minorProtocolVersion).arg(c_databaseVersion).arg(QString::fromStdString(ProofOfWork::name())).arg(ProofOfWork::revision()).arg(dev::Version));
connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved()));
@ -1448,6 +1453,25 @@ void Main::on_inject_triggered()
}
}
void Main::on_injectBlock_triggered()
{
QString s = QInputDialog::getText(this, "Inject Block", "Enter block dump in hex");
try
{
bytes b = fromHex(s.toStdString(), WhenError::Throw);
ethereum()->injectBlock(b);
}
catch (BadHexCharacter& _e)
{
cwarn << "invalid hex character, transaction rejected";
cwarn << boost::diagnostic_information(_e);
}
catch (...)
{
cwarn << "block rejected";
}
}
void Main::on_blocks_currentItemChanged()
{
ui->info->clear();

1
alethzero/MainWin.h

@ -159,6 +159,7 @@ private slots:
void on_killBlockchain_triggered();
void on_clearPending_triggered();
void on_inject_triggered();
void on_injectBlock_triggered();
void on_forceMining_triggered();
void on_usePrivate_triggered();
void on_turboMining_triggered();

2
alethzero/NatspecHandler.cpp

@ -51,7 +51,7 @@ NatspecHandler::~NatspecHandler()
void NatspecHandler::add(dev::h256 const& _contractHash, string const& _doc)
{
m_db->Put(m_writeOptions, _contractHash.ref(), _doc);
cdebug << "Registering NatSpec: " << _contractHash.abridged() << _doc;
cdebug << "Registering NatSpec: " << _contractHash << _doc;
}
string NatspecHandler::retrieve(dev::h256 const& _contractHash) const

6
alethzero/Transact.cpp

@ -168,6 +168,7 @@ static std::string toString(TransactionException _te)
}
}
#if ETH_SOLIDITY
static string getFunctionHashes(dev::solidity::CompilerStack const& _compiler, string const& _contractName)
{
string ret = "";
@ -182,6 +183,7 @@ static string getFunctionHashes(dev::solidity::CompilerStack const& _compiler, s
}
return ret;
}
#endif
static tuple<vector<string>, bytes, string> userInputToCode(string const& _user, bool _opt)
{
@ -197,6 +199,7 @@ static tuple<vector<string>, bytes, string> userInputToCode(string const& _user,
boost::replace_all_copy(u, " ", "");
data = fromHex(u);
}
#if ETH_SOLIDITY
else if (sourceIsSolidity(_user))
{
dev::solidity::CompilerStack compiler(true);
@ -220,6 +223,7 @@ static tuple<vector<string>, bytes, string> userInputToCode(string const& _user,
errors.push_back("Solidity: Uncaught exception");
}
}
#endif
#if ETH_SERPENT
else if (sourceIsSerpent(_user))
{
@ -394,6 +398,7 @@ void Transact::on_send_clicked()
// If execution is a contract creation, add Natspec to
// a local Natspec LEVELDB
ethereum()->submitTransaction(s, value(), m_data, ui->gas->value(), gasPrice());
#if ETH_SOLIDITY
string src = ui->data->toPlainText().toStdString();
if (sourceIsSolidity(src))
try
@ -407,6 +412,7 @@ void Transact::on_send_clicked()
}
}
catch (...) {}
#endif
}
else
ethereum()->submitTransaction(s, value(), m_context->fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice());

113
eth/main.cpp

@ -136,6 +136,7 @@ void help()
<< " -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
<< " --opencl-device <n> When mining using -G/--opencl use OpenCL device n (default: 0)." << endl
<< " -t, --mining-threads <n> Limit number of CPU/GPU miners to n (default: use everything available on selected platform)" << endl
<< "Client networking:" << endl
<< " --client-name <name> Add a name to your client's version string (default: blank)." << endl
<< " -b,--bootstrap Connect to the default Ethereum peerserver." << endl
@ -370,7 +371,7 @@ void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod)
for (unsigned i = 0; !completed; ++i)
{
if (current)
cnote << "Mining on PoWhash" << current.headerHash.abridged() << ": " << f.miningProgress();
cnote << "Mining on PoWhash" << current.headerHash << ": " << f.miningProgress();
else
cnote << "Getting work package...";
Json::Value v = rpc.eth_getWork();
@ -380,12 +381,12 @@ void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod)
current.headerHash = hh;
current.seedHash = h256(v[1].asString());
current.boundary = h256(fromHex(v[2].asString()), h256::AlignRight);
cnote << "Got work package:" << current.headerHash.abridged() << " < " << current.boundary;
cnote << "Got work package:" << current.headerHash << " < " << current.boundary;
f.setWork(current);
}
this_thread::sleep_for(chrono::milliseconds(_recheckPeriod));
}
cnote << "Solution found; submitting [" << solution.nonce << "," << current.headerHash.abridged() << "," << solution.mixHash.abridged() << "] to" << _remote << "...";
cnote << "Solution found; submitting [" << solution.nonce << "," << current.headerHash << "," << solution.mixHash << "] to" << _remote << "...";
bool ok = rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(current.headerHash), "0x" + toString(solution.mixHash));
if (ok)
clog(HappyChannel) << "Submitted and accepted.";
@ -405,6 +406,72 @@ void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod)
int main(int argc, char** argv)
{
cout << "\x1b[30mEthBlack\x1b[0m" << endl;
cout << "\x1b[90mEthCoal\x1b[0m" << endl;
cout << "\x1b[37mEthGray\x1b[0m" << endl;
cout << "\x1b[97mEthWhite\x1b[0m" << endl;
cout << "\x1b[31mEthRed\x1b[0m" << endl;
cout << "\x1b[32mEthGreen\x1b[0m" << endl;
cout << "\x1b[33mEthYellow\x1b[0m" << endl;
cout << "\x1b[34mEthBlue\x1b[0m" << endl;
cout << "\x1b[35mEthPurple\x1b[0m" << endl;
cout << "\x1b[36mEthCyan\x1b[0m" << endl;
// High Intensity
cout << "\x1b[91mEthRedI\x1b[0m" << endl;
cout << "\x1b[92mEthLime\x1b[0m" << endl;
cout << "\x1b[93mEthYellowI\x1b[0m" << endl;
cout << "\x1b[94mEthBlueI\x1b[0m" << endl;
cout << "\x1b[95mEthPurpleI\x1b[0m" << endl;
cout << "\x1b[96mEthCyanI\x1b[0m" << endl;
// Bold
cout << "\x1b[1;30mEthBlackB\x1b[0m" << endl;
cout << "\x1b[1;90mEthCoalB\x1b[0m" << endl;
cout << "\x1b[1;37mEthGrayB\x1b[0m" << endl;
cout << "\x1b[1;97mEthWhiteB\x1b[0m" << endl;
cout << "\x1b[1;31mEthRedB\x1b[0m" << endl;
cout << "\x1b[1;32mEthGreenB\x1b[0m" << endl;
cout << "\x1b[1;33mEthYellowB\x1b[0m" << endl;
cout << "\x1b[1;34mEthBlueB\x1b[0m" << endl;
cout << "\x1b[1;35mEthPurpleB\x1b[0m" << endl;
cout << "\x1b[1;36mEthCyanB\x1b[0m" << endl;
// Bold High Intensity
cout << "\x1b[1;91mEthRedBI\x1b[0m" << endl;
cout << "\x1b[1;92mEthGreenBI\x1b[0m" << endl;
cout << "\x1b[1;93mEthYellowBI\x1b[0m" << endl;
cout << "\x1b[1;94mEthBlueBI\x1b[0m" << endl;
cout << "\x1b[1;95mEthPurpleBI\x1b[0m" << endl;
cout << "\x1b[1;96mEthCyanBI\x1b[0m" << endl;
// Background
cout << "\x1b[40mEthBlackOn\x1b[0m" << endl;
cout << "\x1b[100mEthCoalOn\x1b[0m" << endl;
cout << "\x1b[47mEthGrayOn\x1b[0m" << endl;
cout << "\x1b[107mEthWhiteOn\x1b[0m" << endl;
cout << "\x1b[41mEthRedOn\x1b[0m" << endl;
cout << "\x1b[42mEthGreenOn\x1b[0m" << endl;
cout << "\x1b[43mEthYellowOn\x1b[0m" << endl;
cout << "\x1b[44mEthBlueOn\x1b[0m" << endl;
cout << "\x1b[45mEthPurpleOn\x1b[0m" << endl;
cout << "\x1b[46mEthCyanOn\x1b[0m" << endl;
// High Intensity backgrounds
cout << "\x1b[101mEthRedOnI\x1b[0m" << endl;
cout << "\x1b[102mEthGreenOnI\x1b[0m" << endl;
cout << "\x1b[103mEthYellowOnI\x1b[0m" << endl;
cout << "\x1b[104mEthBlueOnI\x1b[0m" << endl;
cout << "\x1b[105mEthPurpleOnI\x1b[0m" << endl;
cout << "\x1b[106mEthCyanOnI\x1b[0m" << endl;
// Underline
cout << "\x1b[4;30mEthBlackU\x1b[0m" << endl;
cout << "\x1b[4;31mEthRedU\x1b[0m" << endl;
cout << "\x1b[4;32mEthGreenU\x1b[0m" << endl;
cout << "\x1b[4;33mEthYellowU\x1b[0m" << endl;
cout << "\x1b[4;34mEthBlueU\x1b[0m" << endl;
cout << "\x1b[4;35mEthPurpleU\x1b[0m" << endl;
cout << "\x1b[4;36mEthCyanU\x1b[0m" << endl;
cout << "\x1b[4;37mEthWhiteU\x1b[0m" << endl;
// Init defaults
Defaults::get();
@ -416,6 +483,7 @@ int main(int argc, char** argv)
MinerType minerType = MinerType::CPU;
unsigned openclPlatform = 0;
unsigned openclDevice = 0;
unsigned miningThreads = UINT_MAX;
/// File name for import/export.
string filename;
@ -534,13 +602,13 @@ int main(int argc, char** argv)
}
else if (arg == "--opencl-platform" && i + 1 < argc)
try {
openclPlatform= stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
openclPlatform = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
else if (arg == "--opencl-device" && i + 1 < argc)
try {
openclDevice = stol(argv[++i]);
@ -784,6 +852,17 @@ int main(int argc, char** argv)
return -1;
}
}
else if ((arg == "-t" || arg == "--mining-threads") && i + 1 < argc)
{
try {
miningThreads = stol(argv[++i]);
}
catch (...)
{
cerr << "Bad " << arg << " option: " << argv[i] << endl;
return -1;
}
}
else if (arg == "-b" || arg == "--bootstrap")
bootstrap = true;
else if (arg == "-f" || arg == "--force-mining")
@ -839,8 +918,16 @@ int main(int argc, char** argv)
if (sessionSecret)
sigKey = KeyPair(sessionSecret);
ProofOfWork::GPUMiner::setDefaultPlatform(openclPlatform);
ProofOfWork::GPUMiner::setDefaultDevice(openclDevice);
if (minerType == MinerType::CPU)
ProofOfWork::CPUMiner::setNumInstances(miningThreads);
else if (minerType == MinerType::GPU)
{
ProofOfWork::GPUMiner::setDefaultPlatform(openclPlatform);
ProofOfWork::GPUMiner::setDefaultDevice(openclDevice);
ProofOfWork::GPUMiner::setNumInstances(miningThreads);
}
// Two codepaths is necessary since named block require database, but numbered
// blocks are superuseful to have when database is already open in another process.
@ -860,7 +947,7 @@ int main(int argc, char** argv)
VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter);
auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp);
auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp");
std::string clientImplString = "Ethereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) + (jit ? "/JIT" : "");
std::string clientImplString = "++eth/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) + (jit ? "/JIT" : "");
dev::WebThreeDirect web3(
clientImplString,
dbPath,

9
exp/main.cpp

@ -22,7 +22,14 @@
#if ETH_ETHASHCL
#define __CL_ENABLE_EXCEPTIONS
#define CL_USE_DEPRECATED_OPENCL_2_0_APIS
#include "libethash-cl/cl.hpp"
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#include <libethash-cl/cl.hpp>
#pragma clang diagnostic pop
#else
#include <libethash-cl/cl.hpp>
#endif
#endif
#include <functional>
#include <boost/filesystem.hpp>

2
libdevcore/Common.cpp

@ -27,7 +27,7 @@ using namespace dev;
namespace dev
{
char const* Version = "0.9.12";
char const* Version = "0.9.13";
}

4
libdevcore/CommonIO.h

@ -77,7 +77,11 @@ template <class T, class U> inline std::ostream& operator<<(std::ostream& _out,
template <class T, class U> inline std::ostream& operator<<(std::ostream& _out, std::multimap<T, U> const& _e);
template <class _S, class _T> _S& operator<<(_S& _out, std::shared_ptr<_T> const& _p);
#ifdef _WIN32
template <class T> inline std::string toString(std::chrono::time_point<T> const& _e, std::string _format = "%Y-%m-%d %H:%M:%S")
#else
template <class T> inline std::string toString(std::chrono::time_point<T> const& _e, std::string _format = "%F %T")
#endif
{
unsigned long milliSecondsSinceEpoch = std::chrono::duration_cast<std::chrono::milliseconds>(_e.time_since_epoch()).count();
auto const durationSinceEpoch = std::chrono::milliseconds(milliSecondsSinceEpoch);

37
libdevcore/Log.cpp

@ -28,10 +28,47 @@
using namespace std;
using namespace dev;
//⊳⊲◀▶■▣▢□▷◁▧▨▩▲◆◉◈◇◎●◍◌○◼☑☒☎☢☣☰☀♽♥♠✩✭❓✔✓✖✕✘✓✔✅⚒⚡⦸⬌∅⁕«««»»»⚙
// Logging
int dev::g_logVerbosity = 5;
map<type_info const*, bool> dev::g_logOverride;
#ifdef _WIN32
const char* LogChannel::name() { return EthGray "..."; }
const char* LeftChannel::name() { return EthNavy "<--"; }
const char* RightChannel::name() { return EthGreen "-->"; }
const char* WarnChannel::name() { return EthOnRed EthBlackBold " X"; }
const char* NoteChannel::name() { return EthBlue " i"; }
const char* DebugChannel::name() { return EthWhite " D"; }
#else
const char* LogChannel::name() { return EthGray "···"; }
const char* LeftChannel::name() { return EthNavy "◀▬▬"; }
const char* RightChannel::name() { return EthGreen "▬▬▶"; }
const char* WarnChannel::name() { return EthOnRed EthBlackBold ""; }
const char* NoteChannel::name() { return EthBlue ""; }
const char* DebugChannel::name() { return EthWhite ""; }
#endif
LogOutputStreamBase::LogOutputStreamBase(char const* _id, std::type_info const* _info, unsigned _v, bool _autospacing):
m_autospacing(_autospacing),
m_verbosity(_v)
{
auto it = g_logOverride.find(_info);
if ((it != g_logOverride.end() && it->second == true) || (it == g_logOverride.end() && (int)_v <= g_logVerbosity))
{
time_t rawTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
char buf[24];
if (strftime(buf, 24, "%X", localtime(&rawTime)) == 0)
buf[0] = '\0'; // empty if case strftime fails
static char const* c_begin = " " EthViolet;
static char const* c_sep1 = EthReset EthBlack "|" EthNavy;
static char const* c_sep2 = EthReset EthBlack "|" EthTeal;
static char const* c_end = EthReset " ";
m_sstr << _id << c_begin << buf << c_sep1 << getThreadName() << ThreadContext::join(c_sep2) << c_end;
}
}
/// Associate a name with each thread for nice logging.
struct ThreadLocalLogName
{

140
libdevcore/Log.h

@ -26,8 +26,13 @@
#include <ctime>
#include <chrono>
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include "vector_ref.h"
#include "Common.h"
#include "CommonIO.h"
#include "CommonData.h"
#include "FixedHash.h"
#include "Terminal.h"
namespace dev
{
@ -74,42 +79,129 @@ std::string getThreadName();
/// The default logging channels. Each has an associated verbosity and three-letter prefix (name() ).
/// Channels should inherit from LogChannel and define name() and verbosity.
struct LogChannel { static const char* name() { return " "; } static const int verbosity = 1; };
struct LeftChannel: public LogChannel { static const char* name() { return "<<<"; } };
struct RightChannel: public LogChannel { static const char* name() { return ">>>"; } };
struct WarnChannel: public LogChannel { static const char* name() { return "!!!"; } static const int verbosity = 0; };
struct NoteChannel: public LogChannel { static const char* name() { return "***"; } };
struct DebugChannel: public LogChannel { static const char* name() { return "---"; } static const int verbosity = 0; };
struct LogChannel { static const char* name(); static const int verbosity = 1; };
struct LeftChannel: public LogChannel { static const char* name(); };
struct RightChannel: public LogChannel { static const char* name(); };
struct WarnChannel: public LogChannel { static const char* name(); static const int verbosity = 0; };
struct NoteChannel: public LogChannel { static const char* name(); };
struct DebugChannel: public LogChannel { static const char* name(); static const int verbosity = 0; };
enum LogTag
{
None,
url,
error
};
/// Logging class, iostream-like, that can be shifted to.
template <class Id, bool _AutoSpacing = true>
class LogOutputStream
class LogOutputStreamBase
{
public:
/// Construct a new object.
/// If _term is true the the prefix info is terminated with a ']' character; if not it ends only with a '|' character.
LogOutputStream(bool _term = true)
LogOutputStreamBase(char const* _id, std::type_info const* _info, unsigned _v, bool _autospacing);
void comment(std::string const& _t)
{
switch (m_logTag)
{
case url: m_sstr << EthNavyUnder; break;
case error: m_sstr << EthRedBold; break;
default:;
}
m_sstr << _t << EthReset;
m_logTag = None;
}
void append(unsigned long _t) { m_sstr << EthBlue << _t << EthReset; }
void append(long _t) { m_sstr << EthBlue << _t << EthReset; }
void append(unsigned int _t) { m_sstr << EthBlue << _t << EthReset; }
void append(int _t) { m_sstr << EthBlue << _t << EthReset; }
void append(bigint const& _t) { m_sstr << EthNavy << _t << EthReset; }
void append(u256 const& _t) { m_sstr << EthNavy << _t << EthReset; }
void append(u160 const& _t) { m_sstr << EthNavy << _t << EthReset; }
void append(double _t) { m_sstr << EthBlue << _t << EthReset; }
template <unsigned N> void append(FixedHash<N> const& _t) { m_sstr << EthTeal "#" << _t.abridged() << EthReset; }
void append(h160 const& _t) { m_sstr << EthRed "@" << _t.abridged() << EthReset; }
void append(h256 const& _t) { m_sstr << EthCyan "#" << _t.abridged() << EthReset; }
void append(h512 const& _t) { m_sstr << EthTeal "##" << _t.abridged() << EthReset; }
void append(std::string const& _t) { m_sstr << EthGreen "\"" + _t + "\"" EthReset; }
void append(bytes const& _t) { m_sstr << EthYellow "%" << toHex(_t) << EthReset; }
void append(bytesConstRef _t) { m_sstr << EthYellow "%" << toHex(_t) << EthReset; }
template <class T> void append(std::vector<T> const& _t)
{
m_sstr << EthWhite "[" EthReset;
int n = 0;
for (auto const& i: _t)
{
m_sstr << (n++ ? EthWhite ", " EthReset : "");
append(i);
}
m_sstr << EthWhite "]" EthReset;
}
template <class T> void append(std::set<T> const& _t)
{
m_sstr << EthYellow "{" EthReset;
int n = 0;
for (auto const& i: _t)
{
m_sstr << (n++ ? EthYellow ", " EthReset : "");
append(i);
}
m_sstr << EthYellow "}" EthReset;
}
template <class T, class U> void append(std::map<T, U> const& _t)
{
std::type_info const* i = &typeid(Id);
auto it = g_logOverride.find(i);
if ((it != g_logOverride.end() && it->second == true) || (it == g_logOverride.end() && Id::verbosity <= g_logVerbosity))
m_sstr << EthLime "{" EthReset;
int n = 0;
for (auto const& i: _t)
{
time_t rawTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
char buf[24];
if (strftime(buf, 24, "%X", localtime(&rawTime)) == 0)
buf[0] = '\0'; // empty if case strftime fails
m_sstr << Id::name() << " [ " << buf << " | " << getThreadName() << ThreadContext::join(" | ") << (_term ? " ] " : "");
m_sstr << (n++ ? EthLime ", " EthReset : "");
append(i.first);
m_sstr << (n++ ? EthLime ": " EthReset : "");
append(i.second);
}
m_sstr << EthLime "}" EthReset;
}
template <class T, class U> void append(std::pair<T, U> const& _t)
{
m_sstr << EthPurple "(" EthReset;
append(_t.first);
m_sstr << EthPurple ", " EthReset;
append(_t.second);
m_sstr << EthPurple ")" EthReset;
}
template <class T> void append(T const& _t)
{
m_sstr << toString(_t);
}
template <class T> void append(boost::asio::ip::tcp::endpoint const& _t)
{
m_sstr << EthNavyUnder "tcp://" << _t << EthReset;
}
protected:
bool m_autospacing = false;
unsigned m_verbosity = 0;
std::stringstream m_sstr; ///< The accrued log entry.
LogTag m_logTag;
};
/// Logging class, iostream-like, that can be shifted to.
template <class Id, bool _AutoSpacing = true>
class LogOutputStream: LogOutputStreamBase
{
public:
/// Construct a new object.
/// If _term is true the the prefix info is terminated with a ']' character; if not it ends only with a '|' character.
LogOutputStream(): LogOutputStreamBase(Id::name(), &typeid(Id), Id::verbosity, _AutoSpacing) {}
/// Destructor. Posts the accrued log entry to the g_logPost function.
~LogOutputStream() { if (Id::verbosity <= g_logVerbosity) g_logPost(m_sstr.str(), Id::name()); }
/// Shift arbitrary data to the log. Spaces will be added between items as required.
template <class T> LogOutputStream& operator<<(T const& _t) { if (Id::verbosity <= g_logVerbosity) { if (_AutoSpacing && m_sstr.str().size() && m_sstr.str().back() != ' ') m_sstr << " "; m_sstr << _t; } return *this; }
LogOutputStream& operator<<(std::string const& _t) { if (Id::verbosity <= g_logVerbosity) { if (_AutoSpacing && m_sstr.str().size() && m_sstr.str().back() != ' ') m_sstr << " "; comment(_t); } return *this; }
private:
std::stringstream m_sstr; ///< The accrued log entry.
LogOutputStream& operator<<(LogTag _t) { m_logTag = _t; return *this; }
/// Shift arbitrary data to the log. Spaces will be added between items as required.
template <class T> LogOutputStream& operator<<(T const& _t) { if (Id::verbosity <= g_logVerbosity) { if (_AutoSpacing && m_sstr.str().size() && m_sstr.str().back() != ' ') m_sstr << " "; append(_t); } return *this; }
};
// Simple cout-like stream objects for accessing common log channels.

6
libdevcore/RLP.cpp

@ -166,6 +166,9 @@ unsigned RLP::length() const
{
if ((int)m_data.size() <= n - c_rlpDataIndLenZero)
BOOST_THROW_EXCEPTION(BadRLP());
if ((int)m_data.size() > 1)
if (m_data[1] == 0)
BOOST_THROW_EXCEPTION(BadRLP());
for (int i = 0; i < n - c_rlpDataIndLenZero; ++i)
ret = (ret << 8) | m_data[i + 1];
}
@ -175,6 +178,9 @@ unsigned RLP::length() const
{
if ((int)m_data.size() <= n - c_rlpListIndLenZero)
BOOST_THROW_EXCEPTION(BadRLP());
if ((int)m_data.size() > 1)
if (m_data[1] == 0)
BOOST_THROW_EXCEPTION(BadRLP());
for (int i = 0; i < n - c_rlpListIndLenZero; ++i)
ret = (ret << 8) | m_data[i + 1];
}

2
libdevcore/RLP.h

@ -308,7 +308,7 @@ private:
/// Single-byte data payload.
bool isSingleByte() const { return !isNull() && m_data[0] < c_rlpDataImmLenStart; }
/// @returns the bytes used to encode the length of the data. Valid for all types.
/// @returns the amount of bytes used to encode the length of the data. Valid for all types.
unsigned lengthSize() const { if (isData() && m_data[0] > c_rlpDataIndLenZero) return m_data[0] - c_rlpDataIndLenZero; if (isList() && m_data[0] > c_rlpListIndLenZero) return m_data[0] - c_rlpListIndLenZero; return 0; }
/// @returns the size in bytes of the payload, as given by the RLP as opposed to as inferred from m_data.

148
libdevcore/Terminal.h

@ -0,0 +1,148 @@
#pragma once
namespace dev
{
namespace con
{
#ifdef _WIN32
#define EthReset "" // Text Reset
#define EthReset "" // Text Reset
// Regular Colors
#define EthBlack "" // Black
#define EthCoal "" // Black
#define EthGray "" // White
#define EthWhite "" // White
#define EthMaroon "" // Red
#define EthRed "" // Red
#define EthGreen "" // Green
#define EthLime "" // Green
#define EthOrange "" // Yellow
#define EthYellow "" // Yellow
#define EthNavy "" // Blue
#define EthBlue "" // Blue
#define EthViolet "" // Purple
#define EthPurple "" // Purple
#define EthTeal "" // Cyan
#define EthCyan "" // Cyan
#define EthBlackBold "" // Black
#define EthCoalBold "" // Black
#define EthGrayBold "" // White
#define EthWhiteBold "" // White
#define EthMaroonBold "" // Red
#define EthRedBold "" // Red
#define EthGreenBold "" // Green
#define EthLimeBold "" // Green
#define EthOrangeBold "" // Yellow
#define EthYellowBold "" // Yellow
#define EthNavyBold "" // Blue
#define EthBlueBold "" // Blue
#define EthVioletBold "" // Purple
#define EthPurpleBold "" // Purple
#define EthTealBold "" // Cyan
#define EthCyanBold "" // Cyan
// Background
#define EthOnBlack "" // Black
#define EthOnCoal "" // Black
#define EthOnGray "" // White
#define EthOnWhite "" // White
#define EthOnMaroon "" // Red
#define EthOnRed "" // Red
#define EthOnGreen "" // Green
#define EthOnLime "" // Green
#define EthOnOrange "" // Yellow
#define EthOnYellow "" // Yellow
#define EthOnNavy "" // Blue
#define EthOnBlue "" // Blue
#define EthOnViolet "" // Purple
#define EthOnPurple "" // Purple
#define EthOnTeal "" // Cyan
#define EthOnCyan "" // Cyan
// Underline
#define EthBlackUnder "" // Black
#define EthGrayUnder "" // White
#define EthMaroonUnder "" // Red
#define EthGreenUnder "" // Green
#define EthOrangeUnder "" // Yellow
#define EthNavyUnder "" // Blue
#define EthVioletUnder "" // Purple
#define EthTealUnder "" // Cyan
#else
#define EthReset "\x1b[0m" // Text Reset
// Regular Colors
#define EthBlack "\x1b[30m" // Black
#define EthCoal "\x1b[90m" // Black
#define EthGray "\x1b[37m" // White
#define EthWhite "\x1b[97m" // White
#define EthMaroon "\x1b[31m" // Red
#define EthRed "\x1b[91m" // Red
#define EthGreen "\x1b[32m" // Green
#define EthLime "\x1b[92m" // Green
#define EthOrange "\x1b[33m" // Yellow
#define EthYellow "\x1b[93m" // Yellow
#define EthNavy "\x1b[34m" // Blue
#define EthBlue "\x1b[94m" // Blue
#define EthViolet "\x1b[35m" // Purple
#define EthPurple "\x1b[95m" // Purple
#define EthTeal "\x1b[36m" // Cyan
#define EthCyan "\x1b[96m" // Cyan
#define EthBlackBold "\x1b[1;30m" // Black
#define EthCoalBold "\x1b[1;90m" // Black
#define EthGrayBold "\x1b[1;37m" // White
#define EthWhiteBold "\x1b[1;97m" // White
#define EthMaroonBold "\x1b[1;31m" // Red
#define EthRedBold "\x1b[1;91m" // Red
#define EthGreenBold "\x1b[1;32m" // Green
#define EthLimeBold "\x1b[1;92m" // Green
#define EthOrangeBold "\x1b[1;33m" // Yellow
#define EthYellowBold "\x1b[1;93m" // Yellow
#define EthNavyBold "\x1b[1;34m" // Blue
#define EthBlueBold "\x1b[1;94m" // Blue
#define EthVioletBold "\x1b[1;35m" // Purple
#define EthPurpleBold "\x1b[1;95m" // Purple
#define EthTealBold "\x1b[1;36m" // Cyan
#define EthCyanBold "\x1b[1;96m" // Cyan
// Background
#define EthOnBlack "\x1b[40m" // Black
#define EthOnCoal "\x1b[100m" // Black
#define EthOnGray "\x1b[47m" // White
#define EthOnWhite "\x1b[107m" // White
#define EthOnMaroon "\x1b[41m" // Red
#define EthOnRed "\x1b[101m" // Red
#define EthOnGreen "\x1b[42m" // Green
#define EthOnLime "\x1b[102m" // Green
#define EthOnOrange "\x1b[43m" // Yellow
#define EthOnYellow "\x1b[103m" // Yellow
#define EthOnNavy "\x1b[44m" // Blue
#define EthOnBlue "\x1b[104m" // Blue
#define EthOnViolet "\x1b[45m" // Purple
#define EthOnPurple "\x1b[105m" // Purple
#define EthOnTeal "\x1b[46m" // Cyan
#define EthOnCyan "\x1b[106m" // Cyan
// Underline
#define EthBlackUnder "\x1b[4;30m" // Black
#define EthGrayUnder "\x1b[4;37m" // White
#define EthMaroonUnder "\x1b[4;31m" // Red
#define EthGreenUnder "\x1b[4;32m" // Green
#define EthOrangeUnder "\x1b[4;33m" // Yellow
#define EthNavyUnder "\x1b[4;34m" // Blue
#define EthVioletUnder "\x1b[4;35m" // Purple
#define EthTealUnder "\x1b[4;36m" // Cyan
#endif
}
}

13
libdevcrypto/MemoryDB.cpp

@ -27,6 +27,9 @@ using namespace dev;
namespace dev
{
const char* DBChannel::name() { return "TDB"; }
const char* DBWarn::name() { return "TDB"; }
std::map<h256, std::string> MemoryDB::get() const
{
if (!m_enforceRefs)
@ -46,7 +49,7 @@ std::string MemoryDB::lookup(h256 _h) const
if (!m_enforceRefs || (m_refCount.count(it->first) && m_refCount.at(it->first)))
return it->second;
// else if (m_enforceRefs && m_refCount.count(it->first) && !m_refCount.at(it->first))
// cnote << "Lookup required for value with no refs. Let's hope it's in the DB." << _h.abridged();
// cnote << "Lookup required for value with no refs. Let's hope it's in the DB." << _h;
}
return std::string();
}
@ -64,7 +67,7 @@ void MemoryDB::insert(h256 _h, bytesConstRef _v)
m_over[_h] = _v.toString();
m_refCount[_h]++;
#if ETH_PARANOIA
dbdebug << "INST" << _h.abridged() << "=>" << m_refCount[_h];
dbdebug << "INST" << _h << "=>" << m_refCount[_h];
#endif
}
@ -79,15 +82,15 @@ bool MemoryDB::kill(h256 _h)
{
// If we get to this point, then there was probably a node in the level DB which we need to remove and which we have previously
// used as part of the memory-based MemoryDB. Nothing to be worried about *as long as the node exists in the DB*.
dbdebug << "NOKILL-WAS" << _h.abridged();
dbdebug << "NOKILL-WAS" << _h;
return false;
}
dbdebug << "KILL" << _h.abridged() << "=>" << m_refCount[_h];
dbdebug << "KILL" << _h << "=>" << m_refCount[_h];
return true;
}
else
{
dbdebug << "NOKILL" << _h.abridged();
dbdebug << "NOKILL" << _h;
return false;
}
#else

4
libdevcrypto/MemoryDB.h

@ -31,8 +31,8 @@
namespace dev
{
struct DBChannel: public LogChannel { static const char* name() { return "TDB"; } static const int verbosity = 18; };
struct DBWarn: public LogChannel { static const char* name() { return "TDB"; } static const int verbosity = 1; };
struct DBChannel: public LogChannel { static const char* name(); static const int verbosity = 18; };
struct DBWarn: public LogChannel { static const char* name(); static const int verbosity = 1; };
#define dbdebug clog(DBChannel)
#define dbwarn clog(DBWarn)

2
libdevcrypto/OverlayDB.cpp

@ -103,7 +103,7 @@ void OverlayDB::kill(h256 _h)
if (m_db)
m_db->Get(m_readOptions, ldb::Slice((char const*)_h.data(), 32), &ret);
if (ret.empty())
cnote << "Decreasing DB node ref count below zero with no DB node. Probably have a corrupt Trie." << _h.abridged();
cnote << "Decreasing DB node ref count below zero with no DB node. Probably have a corrupt Trie." << _h;
}
#else
MemoryDB::kill(_h);

2
libdevcrypto/TrieDB.cpp

@ -26,3 +26,5 @@ using namespace dev;
h256 const dev::c_shaNull = sha3(rlp(""));
h256 const dev::EmptyTrie = c_shaNull;
const char* TrieDBChannel::name() { return "-T-"; }

14
libdevcrypto/TrieDB.h

@ -40,7 +40,7 @@ namespace ldb = leveldb;
namespace dev
{
struct TrieDBChannel: public LogChannel { static const char* name() { return "-T-"; } static const int verbosity = 17; };
struct TrieDBChannel: public LogChannel { static const char* name(); static const int verbosity = 17; };
#define tdebug clog(TrieDBChannel)
struct InvalidTrie: virtual dev::Exception {};
@ -120,14 +120,14 @@ public:
if (_r.isList() && _r.itemCount() == 2 && (!_wasExt || _out))
{
if (_out)
(*_out) << std::string(_indent * 2, ' ') << (_wasExt ? "!2 " : "2 ") << sha3(_r.data()).abridged() << ": " << _r << "\n";
(*_out) << std::string(_indent * 2, ' ') << (_wasExt ? "!2 " : "2 ") << sha3(_r.data()) << ": " << _r << "\n";
if (!isLeaf(_r)) // don't go down leaves
descendEntry(_r[1], _keyMask, true, _out, _indent + 1);
}
else if (_r.isList() && _r.itemCount() == 17)
{
if (_out)
(*_out) << std::string(_indent * 2, ' ') << "17 " << sha3(_r.data()).abridged() << ": " << _r << "\n";
(*_out) << std::string(_indent * 2, ' ') << "17 " << sha3(_r.data()) << ": " << _r << "\n";
for (unsigned i = 0; i < 16; ++i)
if (!_r[i].isEmpty()) // 16 branches are allowed to be empty
descendEntry(_r[i], _keyMask, false, _out, _indent + 1);
@ -779,7 +779,7 @@ template <class DB> std::string GenericTrieDB<DB>::atAux(RLP const& _here, Nibbl
template <class DB> bytes GenericTrieDB<DB>::mergeAt(RLP const& _orig, NibbleSlice _k, bytesConstRef _v, bool _inLine)
{
#if ETH_PARANOIA
tdebug << "mergeAt " << _orig << _k << sha3(_orig.data()).abridged();
tdebug << "mergeAt " << _orig << _k << sha3(_orig.data());
#endif
// The caller will make sure that the bytes are inserted properly.
@ -854,7 +854,7 @@ template <class DB> bytes GenericTrieDB<DB>::mergeAt(RLP const& _orig, NibbleSli
template <class DB> void GenericTrieDB<DB>::mergeAtAux(RLPStream& _out, RLP const& _orig, NibbleSlice _k, bytesConstRef _v)
{
#if ETH_PARANOIA
tdebug << "mergeAtAux " << _orig << _k << sha3(_orig.data()).abridged() << ((_orig.isData() && _orig.size() <= 32) ? _orig.toHash<h256>().abridged() : std::string());
tdebug << "mergeAtAux " << _orig << _k << sha3(_orig.data()) << ((_orig.isData() && _orig.size() <= 32) ? _orig.toHash<h256>() : std::string());
#endif
RLP r = _orig;
@ -902,7 +902,7 @@ template <class DB> std::string GenericTrieDB<DB>::deref(RLP const& _n) const
template <class DB> bytes GenericTrieDB<DB>::deleteAt(RLP const& _orig, NibbleSlice _k)
{
#if ETH_PARANOIA
tdebug << "deleteAt " << _orig << _k << sha3(_orig.data()).abridged();
tdebug << "deleteAt " << _orig << _k << sha3(_orig.data());
#endif
// The caller will make sure that the bytes are inserted properly.
@ -1009,7 +1009,7 @@ template <class DB> bytes GenericTrieDB<DB>::deleteAt(RLP const& _orig, NibbleSl
template <class DB> bool GenericTrieDB<DB>::deleteAtAux(RLPStream& _out, RLP const& _orig, NibbleSlice _k)
{
#if ETH_PARANOIA
tdebug << "deleteAtAux " << _orig << _k << sha3(_orig.data()).abridged() << ((_orig.isData() && _orig.size() <= 32) ? _orig.toHash<h256>().abridged() : std::string());
tdebug << "deleteAtAux " << _orig << _k << sha3(_orig.data()) << ((_orig.isData() && _orig.size() <= 32) ? _orig.toHash<h256>() : std::string());
#endif
bytes b = _orig.isEmpty() ? bytes() : deleteAt(_orig.isList() ? _orig : RLP(node(_orig.toHash<h256>())), _k);

21
libethash-cl/ethash_cl_miner.cpp

@ -85,6 +85,27 @@ std::string ethash_cl_miner::platform_info(unsigned _platformId, unsigned _devic
return "{ \"platform\": \"" + platforms[platform_num].getInfo<CL_PLATFORM_NAME>() + "\", \"device\": \"" + device.getInfo<CL_DEVICE_NAME>() + "\", \"version\": \"" + device_version + "\" }";
}
unsigned ethash_cl_miner::get_num_devices(unsigned _platformId)
{
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
if (platforms.empty())
{
debugf("No OpenCL platforms found.\n");
return 0;
}
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())
{
debugf("No OpenCL devices found.\n");
return 0;
}
return devices.size();
}
void ethash_cl_miner::finish()
{
if (m_queue())

2
libethash-cl/ethash_cl_miner.h

@ -33,6 +33,8 @@ public:
bool init(ethash_params const& params, std::function<void(void*)> _fillDAG, unsigned workgroup_size = 64, unsigned _platformId = 0, unsigned _deviceId = 0);
static std::string platform_info(unsigned _platformId = 0, unsigned _deviceId = 0);
static unsigned get_num_devices(unsigned _platformId = 0);
void finish();
void hash(uint8_t* ret, uint8_t const* header, uint64_t nonce, unsigned count);

2
libethcore/Common.cpp

@ -34,7 +34,7 @@ namespace eth
{
const unsigned c_protocolVersion = 60;
const unsigned c_minorProtocolVersion = 0;
const unsigned c_minorProtocolVersion = 1;
const unsigned c_databaseBaseVersion = 9;
#if ETH_FATDB
const unsigned c_databaseVersionModifier = 1;

13
libethcore/Ethash.cpp

@ -121,6 +121,8 @@ bool Ethash::verify(BlockInfo const& _header)
return slow;
}
unsigned Ethash::CPUMiner::s_numInstances = 1;
void Ethash::CPUMiner::workLoop()
{
auto tid = std::this_thread::get_id();
@ -264,10 +266,11 @@ private:
unsigned Ethash::GPUMiner::s_platformId = 0;
unsigned Ethash::GPUMiner::s_deviceId = 0;
unsigned Ethash::GPUMiner::s_numInstances = 1;
Ethash::GPUMiner::GPUMiner(ConstructionInfo const& _ci):
Miner(_ci),
Worker("gpuminer"),
Worker("gpuminer" + toString(index())),
m_hook(new EthashCLHook(this))
{
}
@ -308,7 +311,8 @@ void Ethash::GPUMiner::workLoop()
auto p = EthashAux::params(m_minerSeed);
auto cb = [&](void* d) { EthashAux::full(m_minerSeed, bytesRef((byte*)d, p.full_size)); };
m_miner->init(p, cb, 32, s_platformId, s_deviceId);
unsigned device = instances() > 0 ? index() : s_deviceId;
m_miner->init(p, cb, 32, s_platformId, device);
}
uint64_t upper64OfBoundary = (uint64_t)(u64)((u256)w.boundary >> 192);
@ -331,6 +335,11 @@ std::string Ethash::GPUMiner::platformInfo()
return ethash_cl_miner::platform_info(s_platformId, s_deviceId);
}
unsigned Ethash::GPUMiner::getNumDevices()
{
return ethash_cl_miner::get_num_devices(s_platformId);
}
#endif
}

14
libethcore/Ethash.h

@ -78,17 +78,18 @@ public:
static bool preVerify(BlockInfo const& _header);
static WorkPackage package(BlockInfo const& _header);
static void assignResult(Solution const& _r, BlockInfo& _header) { _header.nonce = _r.nonce; _header.mixHash = _r.mixHash; }
class CPUMiner: public Miner, Worker
{
public:
CPUMiner(ConstructionInfo const& _ci): Miner(_ci), Worker("miner" + toString(index())) {}
static unsigned instances() { return std::thread::hardware_concurrency(); }
static unsigned instances() { return s_numInstances > 0 ? s_numInstances : std::thread::hardware_concurrency(); }
static std::string platformInfo();
static void setDefaultPlatform(unsigned) {}
static void setDefaultDevice(unsigned) {}
static void setNumInstances(unsigned _instances) { s_numInstances = std::min<unsigned>(_instances, std::thread::hardware_concurrency()); }
protected:
void kickOff() override
{
@ -100,7 +101,7 @@ public:
private:
void workLoop() override;
static unsigned s_deviceId;
static unsigned s_numInstances;
};
#if ETH_ETHASHCL || !ETH_TRUE
@ -112,11 +113,13 @@ public:
GPUMiner(ConstructionInfo const& _ci);
~GPUMiner();
static unsigned instances() { return 1; }
static unsigned instances() { return s_numInstances > 0 ? s_numInstances : 1; }
static std::string platformInfo();
static unsigned getNumDevices();
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()); }
protected:
void kickOff() override;
void pause() override;
@ -133,6 +136,7 @@ public:
h256 m_minerSeed; ///< Last seed in m_miner
static unsigned s_platformId;
static unsigned s_deviceId;
static unsigned s_numInstances;
};
#else
using GPUMiner = CPUMiner;

8
libethcore/EthashAux.cpp

@ -75,11 +75,11 @@ h256 EthashAux::seedHash(unsigned _number)
n = get()->m_seedHashes.size() - 1;
}
get()->m_seedHashes.resize(epoch + 1);
cdebug << "Searching for seedHash of epoch " << epoch;
// cdebug << "Searching for seedHash of epoch " << epoch;
for (; n <= epoch; ++n, ret = sha3(ret))
{
get()->m_seedHashes[n] = ret;
cdebug << "Epoch" << n << "is" << ret.abridged();
// cdebug << "Epoch" << n << "is" << ret;
}
}
return get()->m_seedHashes[epoch];
@ -95,12 +95,12 @@ ethash_params EthashAux::params(h256 const& _seedHash)
}
catch (...)
{
cdebug << "Searching for seedHash " << _seedHash.abridged();
// cdebug << "Searching for seedHash " << _seedHash;
for (h256 h; h != _seedHash && epoch < 2048; ++epoch, h = sha3(h), get()->m_epochs[h] = epoch) {}
if (epoch == 2048)
{
std::ostringstream error;
error << "apparent block number for " << _seedHash.abridged() << " is too high; max is " << (ETHASH_EPOCH_LENGTH * 2048);
error << "apparent block number for " << _seedHash << " is too high; max is " << (ETHASH_EPOCH_LENGTH * 2048);
throw std::invalid_argument(error.str());
}
}

108
libethereum/BlockChain.cpp

@ -48,6 +48,18 @@ namespace js = json_spirit;
#define ETH_CATCH 1
#define ETH_TIMED_IMPORTS 0
#ifdef _WIN32
const char* BlockChainDebug::name() { return EthBlue "8" EthWhite " <>"; }
const char* BlockChainWarn::name() { return EthBlue "8" EthOnRed EthBlackBold " X"; }
const char* BlockChainNote::name() { return EthBlue "8" EthBlue " i"; }
const char* BlockChainChat::name() { return EthBlue "8" EthWhite " o"; }
#else
const char* BlockChainDebug::name() { return EthBlue "" EthWhite ""; }
const char* BlockChainWarn::name() { return EthBlue "" EthOnRed EthBlackBold ""; }
const char* BlockChainNote::name() { return EthBlue "" EthBlue ""; }
const char* BlockChainChat::name() { return EthBlue "" EthWhite ""; }
#endif
std::ostream& dev::eth::operator<<(std::ostream& _out, BlockChain const& _bc)
{
string cmp = toBigEndianString(_bc.currentHash());
@ -167,6 +179,7 @@ void BlockChain::open(std::string const& _path, WithExisting _we)
std::string l;
m_extrasDB->Get(m_readOptions, ldb::Slice("best"), &l);
m_lastBlockHash = l.empty() ? m_genesisHash : *(h256*)l.data();
m_lastBlockNumber = number(m_lastBlockHash);
cnote << "Opened blockchain DB. Latest: " << currentHash();
}
@ -177,6 +190,7 @@ void BlockChain::close()
delete m_extrasDB;
delete m_blocksDB;
m_lastBlockHash = m_genesisHash;
m_lastBlockNumber = 0;
m_details.clear();
m_blocks.clear();
}
@ -191,8 +205,7 @@ void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned,
ProfilerStart("BlockChain_rebuild.log");
#endif
// unsigned originalNumber = (unsigned)BlockInfo(oldBlock(m_lastBlockHash)).number;
unsigned originalNumber = number();
unsigned originalNumber = m_lastBlockNumber;
// Keep extras DB around, but under a temp name
delete m_extrasDB;
@ -217,8 +230,13 @@ void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned,
m_blocksBlooms.clear();
m_lastLastHashes.clear();
m_lastBlockHash = genesisHash();
m_lastBlockNumber = 0;
m_details[m_lastBlockHash].totalDifficulty = c_genesisDifficulty;
h256 lastHash = genesisHash();
m_extrasDB->Put(m_writeOptions, toSlice(m_lastBlockHash, ExtraDetails), (ldb::Slice)dev::ref(m_details[m_lastBlockHash].rlp()));
h256 lastHash = m_lastBlockHash;
boost::timer t;
for (unsigned d = 1; d < originalNumber; ++d)
{
@ -236,11 +254,11 @@ void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned,
if (bi.parentHash != lastHash)
{
cwarn << "DISJOINT CHAIN DETECTED; " << bi.hash().abridged() << "#" << d << " -> parent is" << bi.parentHash.abridged() << "; expected" << lastHash.abridged() << "#" << (d - 1);
cwarn << "DISJOINT CHAIN DETECTED; " << bi.hash() << "#" << d << " -> parent is" << bi.parentHash << "; expected" << lastHash << "#" << (d - 1);
return;
}
lastHash = bi.hash();
import(b, s.db(), ImportRequirements::Default);
import(b, s.db(), 0);
}
catch (...)
{
@ -269,16 +287,6 @@ bool contains(T const& _t, V const& _v)
return false;
}
inline string toString(h256s const& _bs)
{
ostringstream out;
out << "[ ";
for (auto i: _bs)
out << i.abridged() << ", ";
out << "]";
return out.str();
}
LastHashes BlockChain::lastHashes(unsigned _n) const
{
Guard l(x_lastLastHashes);
@ -312,14 +320,14 @@ tuple<h256s, h256s, bool> BlockChain::sync(BlockQueue& _bq, OverlayDB const& _st
}
catch (dev::eth::UnknownParent)
{
cwarn << "ODD: Import queue contains block with unknown parent." << boost::current_exception_diagnostic_information();
cwarn << "ODD: Import queue contains block with unknown parent." << error << boost::current_exception_diagnostic_information();
// NOTE: don't reimport since the queue should guarantee everything in the right order.
// Can't continue - chain bad.
badBlocks.push_back(BlockInfo::headerHash(block));
}
catch (Exception const& _e)
{
cnote << "Exception while importing block. Someone (Jeff? That you?) seems to be giving us dodgy blocks!" << diagnostic_information(_e);
cnote << "Exception while importing block. Someone (Jeff? That you?) seems to be giving us dodgy blocks!" << error << diagnostic_information(_e);
// NOTE: don't reimport since the queue should guarantee everything in the right order.
// Can't continue - chain bad.
badBlocks.push_back(BlockInfo::headerHash(block));
@ -400,7 +408,10 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
auto pdata = pd.rlp();
clog(BlockChainDebug) << "Details is returning false despite block known:" << RLP(pdata);
auto parentBlock = block(bi.parentHash);
clog(BlockChainDebug) << "Block:" << RLP(parentBlock);
clog(BlockChainDebug) << "isKnown:" << isKnown(bi.parentHash);
clog(BlockChainDebug) << "last/number:" << m_lastBlockNumber << m_lastBlockHash << bi.number;
clog(BlockChainDebug) << "Block:" << BlockInfo(parentBlock);
clog(BlockChainDebug) << "RLP:" << RLP(parentBlock);
clog(BlockChainDebug) << "DATABASE CORRUPTION: CRITICAL FAILURE";
exit(-1);
}
@ -408,12 +419,12 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
// Check it's not crazy
if (bi.timestamp > (u256)time(0))
{
clog(BlockChainNote) << bi.hash() << ": Future time " << bi.timestamp << " (now at " << time(0) << ")";
clog(BlockChainChat) << bi.hash() << ": Future time " << bi.timestamp << " (now at " << time(0) << ")";
// Block has a timestamp in the future. This is no good.
BOOST_THROW_EXCEPTION(FutureTime());
}
clog(BlockChainNote) << "Attempting import of " << bi.hash().abridged() << "...";
clog(BlockChainChat) << "Attempting import of " << bi.hash() << "...";
#if ETH_TIMED_IMPORTS
preliminaryChecks = t.elapsed();
@ -476,14 +487,15 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
#endif
{
ReadGuard l1(x_blocks);
ReadGuard l2(x_details);
ReadGuard l4(x_receipts);
ReadGuard l5(x_logBlooms);
m_blocksDB->Put(m_writeOptions, toSlice(bi.hash()), (ldb::Slice)ref(_block));
m_extrasDB->Put(m_writeOptions, toSlice(bi.hash(), ExtraDetails), (ldb::Slice)dev::ref(m_details[bi.hash()].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(bi.parentHash, ExtraDetails), (ldb::Slice)dev::ref(m_details[bi.parentHash].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(bi.hash(), ExtraLogBlooms), (ldb::Slice)dev::ref(m_logBlooms[bi.hash()].rlp()));
m_extrasDB->Put(m_writeOptions, toSlice(bi.hash(), ExtraReceipts), (ldb::Slice)dev::ref(m_receipts[bi.hash()].rlp()));
m_blocksDB->Put(m_writeOptions, toSlice(bi.hash()), (ldb::Slice)ref(_block));
}
#if ETH_TIMED_IMPORTS
@ -531,12 +543,6 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
{
unsigned commonIndex;
tie(route, common, commonIndex) = treeRoute(last, bi.hash());
{
WriteGuard l(x_lastBlockHash);
m_lastBlockHash = bi.hash();
}
m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&(bi.hash()), 32));
// Most of the time these two will be equal - only when we're doing a chain revert will they not be
if (common != last)
@ -597,6 +603,14 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
m_extrasDB->Put(m_writeOptions, toSlice(h, ExtraTransactionAddress), (ldb::Slice)dev::ref(m_transactionAddresses[h].rlp()));
}
// FINALLY! change our best hash.
{
WriteGuard l(x_lastBlockHash);
m_lastBlockHash = bi.hash();
m_lastBlockNumber = (unsigned)bi.number;
m_extrasDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&(bi.hash()), 32));
}
clog(BlockChainNote) << " Imported and best" << td << " (#" << bi.number << "). Has" << (details(bi.parentHash).children.size() - 1) << "siblings. Route:" << toString(route);
noteCanonChanged();
@ -609,7 +623,7 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import
}
else
{
clog(BlockChainNote) << " Imported but not best (oTD:" << details(last).totalDifficulty << " > TD:" << td << ")";
clog(BlockChainChat) << " Imported but not best (oTD:" << details(last).totalDifficulty << " > TD:" << td << ")";
}
#if ETH_TIMED_IMPORTS
@ -687,7 +701,7 @@ void BlockChain::clearBlockBlooms(unsigned _begin, unsigned _end)
tuple<h256s, h256, unsigned> BlockChain::treeRoute(h256 const& _from, h256 const& _to, bool _common, bool _pre, bool _post) const
{
// cdebug << "treeRoute" << _from.abridged() << "..." << _to.abridged();
// cdebug << "treeRoute" << _from << "..." << _to;
if (!_from || !_to)
return make_tuple(h256s(), h256(), 0);
h256s ret;
@ -702,7 +716,7 @@ tuple<h256s, h256, unsigned> BlockChain::treeRoute(h256 const& _from, h256 const
ret.push_back(from);
from = details(from).parent;
fn--;
// cdebug << "from:" << fn << _from.abridged();
// cdebug << "from:" << fn << _from;
}
h256 to = _to;
while (fn < tn)
@ -711,7 +725,7 @@ tuple<h256s, h256, unsigned> BlockChain::treeRoute(h256 const& _from, h256 const
back.push_back(to);
to = details(to).parent;
tn--;
// cdebug << "to:" << tn << _to.abridged();
// cdebug << "to:" << tn << _to;
}
for (;; from = details(from).parent, to = details(to).parent)
{
@ -721,7 +735,7 @@ tuple<h256s, h256, unsigned> BlockChain::treeRoute(h256 const& _from, h256 const
back.push_back(to);
fn--;
tn--;
// cdebug << "from:" << fn << _from.abridged() << "; to:" << tn << _to.abridged();
// cdebug << "from:" << fn << _from << "; to:" << tn << _to;
if (from == to)
break;
if (!from)
@ -956,14 +970,24 @@ bool BlockChain::isKnown(h256 const& _hash) const
{
if (_hash == m_genesisHash)
return true;
{
ReadGuard l(x_blocks);
if (m_blocks.count(_hash))
return true;
}
string d;
m_blocksDB->Get(m_readOptions, toSlice(_hash), &d);
return !!d.size();
ETH_READ_GUARDED(x_blocks)
if (!m_blocks.count(_hash))
{
string d;
m_blocksDB->Get(m_readOptions, toSlice(_hash), &d);
if (d.empty())
return false;
}
ETH_READ_GUARDED(x_details)
if (!m_details.count(_hash))
{
string d;
m_extrasDB->Get(m_readOptions, toSlice(_hash, ExtraDetails), &d);
if (d.empty())
return false;
}
return true;
}
bytes BlockChain::block(h256 const& _hash) const
@ -981,9 +1005,9 @@ bytes BlockChain::block(h256 const& _hash) const
string d;
m_blocksDB->Get(m_readOptions, toSlice(_hash), &d);
if (!d.size())
if (d.empty())
{
cwarn << "Couldn't find requested block:" << _hash.abridged();
cwarn << "Couldn't find requested block:" << _hash;
return bytes();
}

11
libethereum/BlockChain.h

@ -56,10 +56,10 @@ struct AlreadyHaveBlock: virtual Exception {};
struct UnknownParent: virtual Exception {};
struct FutureTime: virtual Exception {};
struct BlockChainChat: public LogChannel { static const char* name() { return "-B-"; } static const int verbosity = 7; };
struct BlockChainNote: public LogChannel { static const char* name() { return "=B="; } static const int verbosity = 4; };
struct BlockChainWarn: public LogChannel { static const char* name() { return "=B="; } static const int verbosity = 1; };
struct BlockChainDebug: public LogChannel { static const char* name() { return "#B#"; } static const int verbosity = 0; };
struct BlockChainChat: public LogChannel { static const char* name(); static const int verbosity = 5; };
struct BlockChainNote: public LogChannel { static const char* name(); static const int verbosity = 3; };
struct BlockChainWarn: public LogChannel { static const char* name(); static const int verbosity = 1; };
struct BlockChainDebug: public LogChannel { static const char* name(); static const int verbosity = 0; };
// TODO: Move all this Genesis stuff into Genesis.h/.cpp
std::map<Address, Account> const& genesisState();
@ -185,7 +185,7 @@ public:
/// Get a number for the given hash (or the most recent mined if none given). Thread-safe.
unsigned number(h256 const& _hash) const { return details(_hash).number; }
unsigned number() const { return number(currentHash()); }
unsigned number() const { return m_lastBlockNumber; }
/// Get a given block (RLP format). Thread-safe.
h256 currentHash() const { ReadGuard l(x_lastBlockHash); return m_lastBlockHash; }
@ -315,6 +315,7 @@ private:
/// Hash of the last (valid) block on the longest chain.
mutable boost::shared_mutex x_lastBlockHash;
h256 m_lastBlockHash;
unsigned m_lastBlockNumber = 0;
/// Genesis block info.
h256 m_genesisHash;

10
libethereum/BlockQueue.cpp

@ -29,12 +29,18 @@ using namespace std;
using namespace dev;
using namespace dev::eth;
#ifdef _WIN32
const char* BlockQueueChannel::name() { return EthOrange "[]>"; }
#else
const char* BlockQueueChannel::name() { return EthOrange "▣┅▶"; }
#endif
ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, bool _isOurs)
{
// Check if we already know this block.
h256 h = BlockInfo::headerHash(_block);
cblockq << "Queuing block" << h.abridged() << "for import...";
cblockq << "Queuing block" << h << "for import...";
UpgradableGuard l(m_lock);
@ -93,7 +99,7 @@ ImportResult BlockQueue::import(bytesConstRef _block, BlockChain const& _bc, boo
else if (!m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !_bc.isKnown(bi.parentHash))
{
// We don't know the parent (yet) - queue it up for later. It'll get resent to us if we find out about its ancestry later on.
cblockq << "OK - queued as unknown parent:" << bi.parentHash.abridged();
cblockq << "OK - queued as unknown parent:" << bi.parentHash;
m_unknown.insert(make_pair(bi.parentHash, make_pair(h, _block.toBytes())));
m_unknownSet.insert(h);

2
libethereum/BlockQueue.h

@ -35,7 +35,7 @@ namespace eth
class BlockChain;
struct BlockQueueChannel: public LogChannel { static const char* name() { return "[]Q"; } static const int verbosity = 4; };
struct BlockQueueChannel: public LogChannel { static const char* name(); static const int verbosity = 4; };
#define cblockq dev::LogOutputStream<dev::eth::BlockQueueChannel, true>()
struct BlockQueueStatus

37
libethereum/Client.cpp

@ -124,6 +124,18 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, ActivityReport const& _r)
return _out;
}
#ifdef _WIN32
const char* ClientNote::name() { return EthTeal "^" EthBlue " i"; }
const char* ClientChat::name() { return EthTeal "^" EthWhite " o"; }
const char* ClientTrace::name() { return EthTeal "^" EthGray " O"; }
const char* ClientDetail::name() { return EthTeal "^" EthCoal " 0"; }
#else
const char* ClientNote::name() { return EthTeal "" EthBlue ""; }
const char* ClientChat::name() { return EthTeal "" EthWhite ""; }
const char* ClientTrace::name() { return EthTeal "" EthGray ""; }
const char* ClientDetail::name() { return EthTeal "" EthCoal ""; }
#endif
Client::Client(p2p::Host* _extNet, std::string const& _dbPath, WithExisting _forceAction, u256 _networkId):
Worker("eth"),
m_vc(_dbPath),
@ -205,20 +217,11 @@ void Client::startedWorking()
// TODO: currently it contains keys for *all* blocks. Make it remove old ones.
cdebug << "startedWorking()";
cdebug << m_bc.number() << m_bc.currentHash();
cdebug << "Pre:" << m_preMine.info();
cdebug << "Post:" << m_postMine.info();
cdebug << "Pre:" << m_preMine.info().headerHash(WithoutNonce) << "; Post:" << m_postMine.info().headerHash(WithoutNonce);
ETH_WRITE_GUARDED(x_preMine)
m_preMine.sync(m_bc);
ETH_WRITE_GUARDED(x_postMine)
ETH_READ_GUARDED(x_preMine)
m_postMine = m_preMine;
cdebug << "Pre:" << m_preMine.info();
cdebug << "Post:" << m_postMine.info();
cdebug << "Pre:" << m_preMine.info().headerHash(WithoutNonce) << "; Post:" << m_postMine.info().headerHash(WithoutNonce);
}
void Client::doneWorking()
@ -295,7 +298,15 @@ static string filtersToString(T const& _fs)
ret << "{";
unsigned i = 0;
for (h256 const& f: _fs)
ret << (i++ ? ", " : "") << (f == PendingChangedFilter ? "pending" : f == ChainChangedFilter ? "chain" : f.abridged());
{
ret << (i++ ? ", " : "");
if (f == PendingChangedFilter)
ret << url << "pending";
else if (f == ChainChangedFilter)
ret << url << "chain";
else
ret << f;
}
ret << "}";
return ret.str();
}
@ -479,7 +490,7 @@ void Client::onChainChanged(ImportRoute const& _ir)
// insert transactions that we are declaring the dead part of the chain
for (auto const& h: _ir.second)
{
clog(ClientNote) << "Dead block:" << h.abridged();
clog(ClientNote) << "Dead block:" << h;
for (auto const& t: m_bc.transactions(h))
{
clog(ClientNote) << "Resubmitting transaction " << Transaction(t, CheckTransaction::None);
@ -490,10 +501,10 @@ void Client::onChainChanged(ImportRoute const& _ir)
// remove transactions from m_tq nicely rather than relying on out of date nonce later on.
for (auto const& h: _ir.first)
{
clog(ClientChat) << "Live block:" << h.abridged();
clog(ClientChat) << "Live block:" << h;
for (auto const& th: m_bc.transactionHashes(h))
{
clog(ClientNote) << "Safely dropping transaction " << th.abridged();
clog(ClientNote) << "Safely dropping transaction " << th;
m_tq.drop(th);
}
}

8
libethereum/Client.h

@ -92,10 +92,10 @@ private:
std::array<u256, 9> m_octiles;
};
struct ClientNote: public LogChannel { static const char* name() { return "*C*"; } static const int verbosity = 2; };
struct ClientChat: public LogChannel { static const char* name() { return "=C="; } static const int verbosity = 4; };
struct ClientTrace: public LogChannel { static const char* name() { return "-C-"; } static const int verbosity = 7; };
struct ClientDetail: public LogChannel { static const char* name() { return " C "; } static const int verbosity = 14; };
struct ClientNote: public LogChannel { static const char* name(); static const int verbosity = 2; };
struct ClientChat: public LogChannel { static const char* name(); static const int verbosity = 4; };
struct ClientTrace: public LogChannel { static const char* name(); static const int verbosity = 7; };
struct ClientDetail: public LogChannel { static const char* name(); static const int verbosity = 14; };
struct ActivityReport
{

5
libethereum/ClientBase.cpp

@ -31,6 +31,11 @@ using namespace std;
using namespace dev;
using namespace dev::eth;
const char* WatchChannel::name() { return EthBlue "" EthWhite " "; }
const char* WorkInChannel::name() { return EthOrange "" EthGreen "▬▶"; }
const char* WorkOutChannel::name() { return EthOrange "" EthNavy "◀▬"; }
const char* WorkChannel::name() { return EthOrange "" EthWhite " "; }
State ClientBase::asOf(BlockNumber _h) const
{
if (_h == PendingBlock)

8
libethereum/ClientBase.h

@ -60,11 +60,11 @@ struct ClientWatch
mutable std::chrono::system_clock::time_point lastPoll = std::chrono::system_clock::now();
};
struct WatchChannel: public LogChannel { static const char* name() { return "(o)"; } static const int verbosity = 7; };
struct WatchChannel: public LogChannel { static const char* name(); static const int verbosity = 7; };
#define cwatch LogOutputStream<WatchChannel, true>()
struct WorkInChannel: public LogChannel { static const char* name() { return ">W>"; } static const int verbosity = 16; };
struct WorkOutChannel: public LogChannel { static const char* name() { return "<W<"; } static const int verbosity = 16; };
struct WorkChannel: public LogChannel { static const char* name() { return "-W-"; } static const int verbosity = 21; };
struct WorkInChannel: public LogChannel { static const char* name(); static const int verbosity = 16; };
struct WorkOutChannel: public LogChannel { static const char* name(); static const int verbosity = 16; };
struct WorkChannel: public LogChannel { static const char* name(); static const int verbosity = 21; };
#define cwork LogOutputStream<WorkChannel, true>()
#define cworkin LogOutputStream<WorkInChannel, true>()
#define cworkout LogOutputStream<WorkOutChannel, true>()

6
libethereum/Executive.cpp

@ -31,6 +31,8 @@ using namespace std;
using namespace dev;
using namespace dev::eth;
const char* VMTraceChannel::name() { return "EVM"; }
Executive::Executive(State& _s, BlockChain const& _bc, unsigned _level):
m_s(_s),
m_lastHashes(_bc.lastHashes((unsigned)_s.info().number - 1)),
@ -199,8 +201,8 @@ OnOpFunc Executive::simpleTrace()
o << " STORAGE" << endl;
for (auto const& i: ext.state().storage(ext.myAddress))
o << showbase << hex << i.first << ": " << i.second << endl;
dev::LogOutputStream<VMTraceChannel, false>(true) << o.str();
dev::LogOutputStream<VMTraceChannel, false>(false) << " | " << dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << hex << setw(4) << setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << dec << vm.gas() << " | -" << dec << gasCost << " | " << newMemSize << "x32" << " ]";
dev::LogOutputStream<VMTraceChannel, false>() << o.str();
dev::LogOutputStream<VMTraceChannel, false>() << " < " << dec << ext.depth << " : " << ext.myAddress << " : #" << steps << " : " << hex << setw(4) << setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " : " << dec << vm.gas() << " : -" << dec << gasCost << " : " << newMemSize << "x32" << " >";
};
}

2
libethereum/Executive.h

@ -35,7 +35,7 @@ class BlockChain;
class ExtVM;
struct Manifest;
struct VMTraceChannel: public LogChannel { static const char* name() { return "EVM"; } static const int verbosity = 11; };
struct VMTraceChannel: public LogChannel { static const char* name(); static const int verbosity = 11; };
/**
* @brief Message-call/contract-creation executor; useful for executing transactions.

13
libethereum/State.cpp

@ -47,6 +47,11 @@ using namespace dev::eth;
static const u256 c_blockReward = 1500 * finney;
const char* StateSafeExceptions::name() { return EthViolet "" EthBlue ""; }
const char* StateDetail::name() { return EthViolet "" EthWhite ""; }
const char* StateTrace::name() { return EthViolet "" EthGray ""; }
const char* StateChat::name() { return EthViolet "" EthWhite ""; }
OverlayDB State::openDB(std::string _path, WithExisting _we)
{
if (_path.empty())
@ -663,7 +668,7 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, ImportRequirement
uncle.verifyParent(uncleParent);
nonces.insert(uncle.nonce);
tdIncrease += uncle.difficulty;
// tdIncrease += uncle.difficulty;
rewarded.push_back(uncle);
}
@ -704,15 +709,15 @@ void State::cleanup(bool _fullCommit)
paranoia("immediately before database commit", true);
// Commit the new trie to disk.
cnote << "Committing to disk: stateRoot" << m_currentBlock.stateRoot.abridged() << "=" << rootHash().abridged() << "=" << toHex(asBytes(m_db.lookup(rootHash())));
clog(StateTrace) << "Committing to disk: stateRoot" << m_currentBlock.stateRoot.abridged() << "=" << rootHash().abridged() << "=" << toHex(asBytes(m_db.lookup(rootHash())));
m_db.commit();
cnote << "Committed: stateRoot" << m_currentBlock.stateRoot.abridged() << "=" << rootHash().abridged() << "=" << toHex(asBytes(m_db.lookup(rootHash())));
clog(StateTrace) << "Committed: stateRoot" << m_currentBlock.stateRoot.abridged() << "=" << rootHash().abridged() << "=" << toHex(asBytes(m_db.lookup(rootHash())));
paranoia("immediately after database commit", true);
m_previousBlock = m_currentBlock;
m_currentBlock.populateFromParent(m_previousBlock);
cdebug << "finalising enactment. current -> previous, hash is" << m_previousBlock.hash().abridged();
clog(StateTrace) << "finalising enactment. current -> previous, hash is" << m_previousBlock.hash().abridged();
}
else
m_db.rollback();

50
libethereum/State.h

@ -50,10 +50,10 @@ namespace eth
class BlockChain;
class State;
struct StateChat: public LogChannel { static const char* name() { return "-S-"; } static const int verbosity = 4; };
struct StateTrace: public LogChannel { static const char* name() { return "=S="; } static const int verbosity = 7; };
struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; };
struct StateSafeExceptions: public LogChannel { static const char* name() { return "(S)"; } static const int verbosity = 21; };
struct StateChat: public LogChannel { static const char* name(); static const int verbosity = 4; };
struct StateTrace: public LogChannel { static const char* name(); static const int verbosity = 7; };
struct StateDetail: public LogChannel { static const char* name(); static const int verbosity = 14; };
struct StateSafeExceptions: public LogChannel { static const char* name(); static const int verbosity = 21; };
enum class BaseState
{
@ -161,15 +161,18 @@ public:
/// This may be called multiple times and without issue.
void commitToMine(BlockChain const& _bc);
/// @returns true iff commitToMine() has been called without any subsequest transactions added &c.
bool isCommittedToMine() const { return m_committedToMine; }
/// Pass in a solution to the proof-of-work.
/// @returns true iff the given nonce is a proof-of-work for this State's block.
/// @returns true iff we were previously committed to mining.
template <class PoW>
bool completeMine(typename PoW::Solution const& _result)
{
PoW::assignResult(_result, m_currentBlock);
if (!m_committedToMine)
return false;
// if (!m_pow.verify(m_currentBlock))
// return false;
PoW::assignResult(_result, m_currentBlock);
cnote << "Completed" << m_currentBlock.headerHash(WithoutNonce).abridged() << m_currentBlock.nonce.abridged() << m_currentBlock.difficulty << PoW::verify(m_currentBlock);
@ -178,24 +181,6 @@ public:
return true;
}
/** Commit to DB and build the final block if the previous call to mine()'s result is completion.
* Typically looks like:
* @code
* while (notYetMined)
* {
* // lock
* commitToMine(_blockChain); // will call uncommitToMine if a repeat.
* // unlock
* MineInfo info;
* for (info.completed = false; !info.completed; info = mine()) {}
* }
* // lock
* completeMine();
* // unlock
* @endcode
*/
void completeMine();
/// Get the complete current block, including valid nonce.
/// Only valid after mine() returns true.
bytes const& blockData() const { return m_currentBytes; }
@ -327,6 +312,19 @@ public:
void resetCurrent();
private:
/** Commit to DB and build the final block if the previous call to mine()'s result is completion.
* Typically looks like:
* @code
* while (notYetMined)
* {
* // lock
* commitToMine(_blockChain); // will call uncommitToMine if a repeat.
* completeMine();
* // unlock
* @endcode
*/
void completeMine();
/// Undo the changes to the state for committing to mine.
void uncommitToMine();

2
libethereum/TransactionQueue.cpp

@ -28,6 +28,8 @@ using namespace std;
using namespace dev;
using namespace dev::eth;
const char* TransactionQueueChannel::name() { return EthCyan "┉┅▶"; }
ImportResult TransactionQueue::import(bytesConstRef _transactionRLP, ImportCallback const& _cb, IfDropped _ik)
{
// Check if we already know this transaction.

2
libethereum/TransactionQueue.h

@ -35,7 +35,7 @@ namespace eth
class BlockChain;
struct TransactionQueueChannel: public LogChannel { static const char* name() { return "->Q"; } static const int verbosity = 4; };
struct TransactionQueueChannel: public LogChannel { static const char* name(); static const int verbosity = 4; };
#define ctxq dev::LogOutputStream<dev::eth::TransactionQueueChannel, true>()
enum class IfDropped { Ignore, Retry };

2
libevmcore/Assembly.cpp

@ -311,7 +311,7 @@ Assembly& Assembly::optimise(bool _enable)
unsigned total = 0;
for (unsigned count = 1; count > 0; total += count)
{
copt << *this;
copt << toString(*this);
count = 0;
copt << "Performing control flow analysis...";

28
libp2p/Common.cpp

@ -32,6 +32,34 @@ const dev::p2p::Node dev::p2p::UnspecifiedNode = dev::p2p::Node(NodeId(), Unspec
bool dev::p2p::NodeIPEndpoint::test_allowLocal = false;
//⊳⊲◀▶■▣▢□▷◁▧▨▩▲◆◉◈◇◎●◍◌○◼☑☒☎☢☣☰☀♽♥♠✩✭❓✔✓✖✕✘✓✔✅⚒⚡⦸⬌∅⁕«««»»»⚙━┅┉▬
#ifdef _WIN32
const char* NetWarn::name() { return EthYellow "N" EthRed " X"; }
const char* NetImpolite::name() { return EthYellow "N" EthRed " !"; }
const char* NetNote::name() { return EthYellow "N" EthBlue " i"; }
const char* NetConnect::name() { return EthYellow "N" EthYellow " C"; }
const char* NetMessageSummary::name() { return EthYellow "N" EthWhite " ."; }
const char* NetMessageDetail::name() { return EthYellow "N" EthGray " o"; }
const char* NetTriviaSummary::name() { return EthYellow "N" EthGray " O"; }
const char* NetTriviaDetail::name() { return EthYellow "N" EthCoal " 0"; }
const char* NetAllDetail::name() { return EthYellow "N" EthCoal " A"; }
const char* NetRight::name() { return EthYellow "N" EthGreen "->"; }
const char* NetLeft::name() { return EthYellow "N" EthNavy "<-"; }
#else
const char* NetWarn::name() { return EthYellow "" EthRed ""; }
const char* NetImpolite::name() { return EthYellow "" EthRed " !"; }
const char* NetNote::name() { return EthYellow "" EthBlue ""; }
const char* NetConnect::name() { return EthYellow "" EthYellow ""; }
const char* NetMessageSummary::name() { return EthYellow "" EthWhite ""; }
const char* NetMessageDetail::name() { return EthYellow "" EthGray ""; }
const char* NetTriviaSummary::name() { return EthYellow "" EthGray ""; }
const char* NetTriviaDetail::name() { return EthYellow "" EthCoal ""; }
const char* NetAllDetail::name() { return EthYellow "" EthCoal ""; }
const char* NetRight::name() { return EthYellow "" EthGreen "▬▶"; }
const char* NetLeft::name() { return EthYellow "" EthNavy "◀▬"; }
#endif
bool p2p::isPublicAddress(std::string const& _addressToCheck)
{
return _addressToCheck.empty() ? false : isPublicAddress(bi::address::from_string(_addressToCheck));

22
libp2p/Common.h

@ -75,17 +75,17 @@ struct NetworkStartRequired: virtual dev::Exception {};
struct InvalidPublicIPAddress: virtual dev::Exception {};
struct InvalidHostIPAddress: virtual dev::Exception {};
struct NetWarn: public LogChannel { static const char* name() { return "!N!"; } static const int verbosity = 0; };
struct NetNote: public LogChannel { static const char* name() { return "*N*"; } static const int verbosity = 1; };
struct NetImpolite: public LogChannel { static const char* name() { return "#!*"; } static const int verbosity = 1; };
struct NetMessageSummary: public LogChannel { static const char* name() { return "-N-"; } static const int verbosity = 2; };
struct NetConnect: public LogChannel { static const char* name() { return "+N+"; } static const int verbosity = 10; };
struct NetMessageDetail: public LogChannel { static const char* name() { return "=N="; } static const int verbosity = 5; };
struct NetTriviaSummary: public LogChannel { static const char* name() { return "-N-"; } static const int verbosity = 10; };
struct NetTriviaDetail: public LogChannel { static const char* name() { return "=N="; } static const int verbosity = 11; };
struct NetAllDetail: public LogChannel { static const char* name() { return "=N="; } static const int verbosity = 13; };
struct NetRight: public LogChannel { static const char* name() { return ">N>"; } static const int verbosity = 14; };
struct NetLeft: public LogChannel { static const char* name() { return "<N<"; } static const int verbosity = 15; };
struct NetWarn: public LogChannel { static const char* name(); static const int verbosity = 0; };
struct NetNote: public LogChannel { static const char* name(); static const int verbosity = 1; };
struct NetImpolite: public LogChannel { static const char* name(); static const int verbosity = 1; };
struct NetMessageSummary: public LogChannel { static const char* name(); static const int verbosity = 2; };
struct NetConnect: public LogChannel { static const char* name(); static const int verbosity = 10; };
struct NetMessageDetail: public LogChannel { static const char* name(); static const int verbosity = 5; };
struct NetTriviaSummary: public LogChannel { static const char* name(); static const int verbosity = 10; };
struct NetTriviaDetail: public LogChannel { static const char* name(); static const int verbosity = 11; };
struct NetAllDetail: public LogChannel { static const char* name(); static const int verbosity = 13; };
struct NetRight: public LogChannel { static const char* name(); static const int verbosity = 14; };
struct NetLeft: public LogChannel { static const char* name(); static const int verbosity = 15; };
enum PacketType
{

2
libp2p/Network.cpp

@ -228,7 +228,7 @@ bi::tcp::endpoint Network::resolveHost(string const& _addr)
bi::tcp::resolver r(s_resolverIoService);
auto it = r.resolve({split[0], toString(port)}, ec);
if (ec)
clog(NetWarn) << "Error resolving host address " << _addr << ":" << ec.message();
clog(NetWarn) << "Error resolving host address..." << url << _addr << ":" << error << ec.message();
else
ep = *it;
}

22
libp2p/NodeTable.cpp

@ -24,6 +24,20 @@ using namespace std;
using namespace dev;
using namespace dev::p2p;
const char* NodeTableWarn::name() { return "!P!"; }
const char* NodeTableNote::name() { return "*P*"; }
const char* NodeTableMessageSummary::name() { return "-P-"; }
const char* NodeTableMessageDetail::name() { return "=P="; }
const char* NodeTableConnect::name() { return "+P+"; }
const char* NodeTableEvent::name() { return "+P+"; }
const char* NodeTableTimer::name() { return "+P+"; }
const char* NodeTableUpdate::name() { return "+P+"; }
const char* NodeTableTriviaSummary::name() { return "-P-"; }
const char* NodeTableTriviaDetail::name() { return "=P="; }
const char* NodeTableAllDetail::name() { return "=P="; }
const char* NodeTableEgress::name() { return ">>P"; }
const char* NodeTableIngress::name() { return "<<P"; }
NodeEntry::NodeEntry(Node _src, Public _pubk, NodeIPEndpoint _gw): Node(_pubk, _gw), distance(NodeTable::distance(_src.id,_pubk)) {}
NodeTable::NodeTable(ba::io_service& _io, KeyPair const& _alias, NodeIPEndpoint const& _endpoint):
@ -73,7 +87,7 @@ shared_ptr<NodeEntry> NodeTable::addNode(Node const& _node)
// we handle when tcp endpoint is 0 below
if (_node.endpoint.address.to_string() == "0.0.0.0")
{
clog(NodeTableWarn) << "addNode Failed. Invalid UDP address 0.0.0.0 for" << _node.id.abridged();
clog(NodeTableWarn) << "addNode Failed. Invalid UDP address" << url << "0.0.0.0" << "for" << _node.id;
return move(shared_ptr<NodeEntry>());
}
@ -382,7 +396,7 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes
// h256 + Signature + type + RLP (smallest possible packet is empty neighbours packet which is 3 bytes)
if (_packet.size() < h256::size + Signature::size + 1 + 3)
{
clog(NodeTableWarn) << "Invalid message size from " << _from.address().to_string() << ":" << _from.port();
clog(NodeTableTriviaSummary) << "Invalid message size from " << _from.address().to_string() << ":" << _from.port();
return;
}
@ -390,7 +404,7 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes
h256 hashSigned(sha3(hashedBytes));
if (!_packet.cropped(0, h256::size).contentsEqual(hashSigned.asBytes()))
{
clog(NodeTableWarn) << "Invalid message hash from " << _from.address().to_string() << ":" << _from.port();
clog(NodeTableTriviaSummary) << "Invalid message hash from " << _from.address().to_string() << ":" << _from.port();
return;
}
@ -402,7 +416,7 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes
Public nodeid(dev::recover(*(Signature const*)sigBytes.data(), sha3(signedBytes)));
if (!nodeid)
{
clog(NodeTableWarn) << "Invalid message signature from " << _from.address().to_string() << ":" << _from.port();
clog(NodeTableTriviaSummary) << "Invalid message signature from " << _from.address().to_string() << ":" << _from.port();
return;
}

26
libp2p/NodeTable.h

@ -416,19 +416,19 @@ struct Neighbours: RLPXDatagram<Neighbours>
void interpretRLP(bytesConstRef _bytes) { RLP r(_bytes); for (auto n: r[0]) nodes.push_back(Node(n)); ts = r[1].toInt<unsigned>(); }
};
struct NodeTableWarn: public LogChannel { static const char* name() { return "!P!"; } static const int verbosity = 0; };
struct NodeTableNote: public LogChannel { static const char* name() { return "*P*"; } static const int verbosity = 1; };
struct NodeTableMessageSummary: public LogChannel { static const char* name() { return "-P-"; } static const int verbosity = 2; };
struct NodeTableMessageDetail: public LogChannel { static const char* name() { return "=P="; } static const int verbosity = 5; };
struct NodeTableConnect: public LogChannel { static const char* name() { return "+P+"; } static const int verbosity = 10; };
struct NodeTableEvent: public LogChannel { static const char* name() { return "+P+"; } static const int verbosity = 10; };
struct NodeTableTimer: public LogChannel { static const char* name() { return "+P+"; } static const int verbosity = 10; };
struct NodeTableUpdate: public LogChannel { static const char* name() { return "+P+"; } static const int verbosity = 10; };
struct NodeTableTriviaSummary: public LogChannel { static const char* name() { return "-P-"; } static const int verbosity = 10; };
struct NodeTableTriviaDetail: public LogChannel { static const char* name() { return "=P="; } static const int verbosity = 11; };
struct NodeTableAllDetail: public LogChannel { static const char* name() { return "=P="; } static const int verbosity = 13; };
struct NodeTableEgress: public LogChannel { static const char* name() { return ">>P"; } static const int verbosity = 14; };
struct NodeTableIngress: public LogChannel { static const char* name() { return "<<P"; } static const int verbosity = 15; };
struct NodeTableWarn: public LogChannel { static const char* name(); static const int verbosity = 0; };
struct NodeTableNote: public LogChannel { static const char* name(); static const int verbosity = 1; };
struct NodeTableMessageSummary: public LogChannel { static const char* name(); static const int verbosity = 2; };
struct NodeTableMessageDetail: public LogChannel { static const char* name(); static const int verbosity = 5; };
struct NodeTableConnect: public LogChannel { static const char* name(); static const int verbosity = 10; };
struct NodeTableEvent: public LogChannel { static const char* name(); static const int verbosity = 10; };
struct NodeTableTimer: public LogChannel { static const char* name(); static const int verbosity = 10; };
struct NodeTableUpdate: public LogChannel { static const char* name(); static const int verbosity = 10; };
struct NodeTableTriviaSummary: public LogChannel { static const char* name(); static const int verbosity = 10; };
struct NodeTableTriviaDetail: public LogChannel { static const char* name(); static const int verbosity = 11; };
struct NodeTableAllDetail: public LogChannel { static const char* name(); static const int verbosity = 13; };
struct NodeTableEgress: public LogChannel { static const char* name(); static const int verbosity = 14; };
struct NodeTableIngress: public LogChannel { static const char* name(); static const int verbosity = 15; };
}
}

8
libp2p/RLPxHandshake.cpp

@ -249,7 +249,7 @@ void RLPXHandshake::transition(boost::system::error_code _ech)
bytesRef frame(&m_handshakeInBuffer);
if (!m_io->authAndDecryptFrame(frame))
{
clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: decrypt failed";
clog(NetTriviaSummary) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: decrypt failed";
m_nextState = Error;
transition();
return;
@ -258,13 +258,13 @@ void RLPXHandshake::transition(boost::system::error_code _ech)
PacketType packetType = (PacketType)(frame[0] == 0x80 ? 0x0 : frame[0]);
if (packetType != 0)
{
clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: invalid packet type";
clog(NetTriviaSummary) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: invalid packet type";
m_nextState = Error;
transition();
return;
}
clog(NetNote) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: success. starting session.";
clog(NetTriviaSummary) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: success. starting session.";
RLP rlp(frame.cropped(1), RLP::ThrowOnFail | RLP::FailIfTooSmall);
m_host->startPeerSession(m_remote, rlp, m_io, m_socket->remoteEndpoint());
}
@ -279,7 +279,7 @@ void RLPXHandshake::transition(boost::system::error_code _ech)
if (!_ec)
{
if (!m_socket->remoteEndpoint().address().is_unspecified())
clog(NetWarn) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Timeout)";
clog(NetConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Timeout)";
cancel();
}
});

12
libp2p/Session.cpp

@ -48,7 +48,8 @@ Session::Session(Host* _s, RLPXFrameIO* _io, std::shared_ptr<Peer> const& _n, Pe
Session::~Session()
{
ThreadContext tc(info().id.abridged() + " | " + info().clientVersion);
ThreadContext tc(info().id.abridged());
ThreadContext tc2(info().clientVersion);
clog(NetMessageSummary) << "Closing peer session :-(";
m_peer->m_lastConnected = m_peer->m_lastAttempted - chrono::seconds(1);
@ -323,7 +324,8 @@ void Session::write()
auto self(shared_from_this());
ba::async_write(m_socket, ba::buffer(bytes), [this, self](boost::system::error_code ec, std::size_t /*length*/)
{
ThreadContext tc(info().id.abridged() + " | " + info().clientVersion);
ThreadContext tc(info().id.abridged());
ThreadContext tc2(info().clientVersion);
// must check queue, as write callback can occur following dropped()
if (ec)
{
@ -397,7 +399,8 @@ void Session::doRead()
auto self(shared_from_this());
ba::async_read(m_socket, boost::asio::buffer(m_data, h256::size), [this,self](boost::system::error_code ec, std::size_t length)
{
ThreadContext tc(info().id.abridged() + " | " + info().clientVersion);
ThreadContext tc(info().id.abridged());
ThreadContext tc2(info().clientVersion);
if (ec && ec.category() != boost::asio::error::get_misc_category() && ec.value() != boost::asio::error::eof)
{
clog(NetWarn) << "Error reading: " << ec.message();
@ -433,7 +436,8 @@ void Session::doRead()
auto tlen = frameSize + ((16 - (frameSize % 16)) % 16) + h128::size;
ba::async_read(m_socket, boost::asio::buffer(m_data, tlen), [this, self, headerRLP, frameSize, tlen](boost::system::error_code ec, std::size_t length)
{
ThreadContext tc(info().id.abridged() + " | " + info().clientVersion);
ThreadContext tc(info().id.abridged());
ThreadContext tc2(info().clientVersion);
if (ec && ec.category() != boost::asio::error::get_misc_category() && ec.value() != boost::asio::error::eof)
{
clog(NetWarn) << "Error reading: " << ec.message();

258
libsolidity/AST.cpp

@ -52,6 +52,7 @@ void ContractDefinition::checkTypeRequirements()
for (ASTPointer<InheritanceSpecifier> const& baseSpecifier: getBaseContracts())
baseSpecifier->checkTypeRequirements();
checkDuplicateFunctions();
checkIllegalOverrides();
checkAbstractFunctions();
checkAbstractConstructors();
@ -87,6 +88,7 @@ void ContractDefinition::checkTypeRequirements()
for (ASTPointer<VariableDeclaration> const& variable: m_stateVariables)
variable->checkTypeRequirements();
checkExternalTypeClashes();
// check for hash collisions in function signatures
set<FixedHash<4>> hashes;
for (auto const& it: getInterfaceFunctionList())
@ -131,6 +133,33 @@ FunctionDefinition const* ContractDefinition::getFallbackFunction() const
return nullptr;
}
void ContractDefinition::checkDuplicateFunctions() const
{
/// Checks that two functions with the same name defined in this contract have different
/// argument types and that there is at most one constructor.
map<string, vector<FunctionDefinition const*>> functions;
for (ASTPointer<FunctionDefinition> const& function: getDefinedFunctions())
functions[function->getName()].push_back(function.get());
if (functions[getName()].size() > 1)
BOOST_THROW_EXCEPTION(
DeclarationError() <<
errinfo_sourceLocation(getLocation()) <<
errinfo_comment("More than one constructor defined.")
);
for (auto const& it: functions)
{
vector<FunctionDefinition const*> const& overloads = it.second;
for (size_t i = 0; i < overloads.size(); ++i)
for (size_t j = i + 1; j < overloads.size(); ++j)
if (FunctionType(*overloads[i]).hasEqualArgumentTypes(FunctionType(*overloads[j])))
BOOST_THROW_EXCEPTION(
DeclarationError() <<
errinfo_sourceLocation(overloads[j]->getLocation()) <<
errinfo_comment("Function with same name and arguments already defined.")
);
}
}
void ContractDefinition::checkAbstractFunctions()
{
map<string, bool> functions;
@ -171,7 +200,7 @@ void ContractDefinition::checkAbstractConstructors()
for (auto const& modifier: constructor->getModifiers())
{
auto baseContract = dynamic_cast<ContractDefinition const*>(
modifier->getName()->getReferencedDeclaration()
&modifier->getName()->getReferencedDeclaration()
);
if (baseContract)
argumentsNeeded.erase(baseContract);
@ -181,7 +210,7 @@ void ContractDefinition::checkAbstractConstructors()
for (ASTPointer<InheritanceSpecifier> const& base: contract->getBaseContracts())
{
auto baseContract = dynamic_cast<ContractDefinition const*>(
base->getName()->getReferencedDeclaration()
&base->getName()->getReferencedDeclaration()
);
solAssert(baseContract, "");
if (!base->getArguments().empty())
@ -196,7 +225,7 @@ void ContractDefinition::checkIllegalOverrides() const
{
// TODO unify this at a later point. for this we need to put the constness and the access specifier
// into the types
map<string, FunctionDefinition const*> functions;
map<string, vector<FunctionDefinition const*>> functions;
map<string, ModifierDefinition const*> modifiers;
// We search from derived to base, so the stored item causes the error.
@ -209,28 +238,67 @@ void ContractDefinition::checkIllegalOverrides() const
string const& name = function->getName();
if (modifiers.count(name))
BOOST_THROW_EXCEPTION(modifiers[name]->createTypeError("Override changes function to modifier."));
FunctionDefinition const*& override = functions[name];
if (!override)
override = function.get();
else if (override->getVisibility() != function->getVisibility() ||
override->isDeclaredConst() != function->isDeclaredConst() ||
FunctionType(*override) != FunctionType(*function))
BOOST_THROW_EXCEPTION(override->createTypeError("Override changes extended function signature."));
FunctionType functionType(*function);
// function should not change the return type
for (FunctionDefinition const* overriding: functions[name])
{
FunctionType overridingType(*overriding);
if (!overridingType.hasEqualArgumentTypes(functionType))
continue;
if (
overriding->getVisibility() != function->getVisibility() ||
overriding->isDeclaredConst() != function->isDeclaredConst() ||
overridingType != functionType
)
BOOST_THROW_EXCEPTION(overriding->createTypeError("Override changes extended function signature."));
}
functions[name].push_back(function.get());
}
for (ASTPointer<ModifierDefinition> const& modifier: contract->getFunctionModifiers())
{
string const& name = modifier->getName();
if (functions.count(name))
BOOST_THROW_EXCEPTION(functions[name]->createTypeError("Override changes modifier to function."));
ModifierDefinition const*& override = modifiers[name];
if (!override)
override = modifier.get();
else if (ModifierType(*override) != ModifierType(*modifier))
BOOST_THROW_EXCEPTION(override->createTypeError("Override changes modifier signature."));
if (!functions[name].empty())
BOOST_THROW_EXCEPTION(override->createTypeError("Override changes modifier to function."));
}
}
}
void ContractDefinition::checkExternalTypeClashes() const
{
map<string, vector<pair<Declaration const*, shared_ptr<FunctionType>>>> externalDeclarations;
for (ContractDefinition const* contract: getLinearizedBaseContracts())
{
for (ASTPointer<FunctionDefinition> const& f: contract->getDefinedFunctions())
if (f->isPartOfExternalInterface())
{
auto functionType = make_shared<FunctionType>(*f);
externalDeclarations[functionType->externalSignature(f->getName())].push_back(
make_pair(f.get(), functionType)
);
}
for (ASTPointer<VariableDeclaration> const& v: contract->getStateVariables())
if (v->isPartOfExternalInterface())
{
auto functionType = make_shared<FunctionType>(*v);
externalDeclarations[functionType->externalSignature(v->getName())].push_back(
make_pair(v.get(), functionType)
);
}
}
for (auto const& it: externalDeclarations)
for (size_t i = 0; i < it.second.size(); ++i)
for (size_t j = i + 1; j < it.second.size(); ++j)
if (!it.second[i].second->hasEqualArgumentTypes(*it.second[j].second))
BOOST_THROW_EXCEPTION(it.second[j].first->createTypeError(
"Function overload clash during conversion to external types for arguments."
));
}
std::vector<ASTPointer<EventDefinition>> const& ContractDefinition::getInterfaceEvents() const
{
if (!m_interfaceEvents)
@ -253,16 +321,21 @@ vector<pair<FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::getIn
if (!m_interfaceFunctionList)
{
set<string> functionsSeen;
set<string> signaturesSeen;
m_interfaceFunctionList.reset(new vector<pair<FixedHash<4>, FunctionTypePointer>>());
for (ContractDefinition const* contract: getLinearizedBaseContracts())
{
for (ASTPointer<FunctionDefinition> const& f: contract->getDefinedFunctions())
if (functionsSeen.count(f->getName()) == 0 && f->isPartOfExternalInterface())
{
string functionSignature = f->externalSignature();
if (f->isPartOfExternalInterface() && signaturesSeen.count(functionSignature) == 0)
{
functionsSeen.insert(f->getName());
FixedHash<4> hash(dev::sha3(f->externalSignature()));
signaturesSeen.insert(functionSignature);
FixedHash<4> hash(dev::sha3(functionSignature));
m_interfaceFunctionList->push_back(make_pair(hash, make_shared<FunctionType>(*f, false)));
}
}
for (ASTPointer<VariableDeclaration> const& v: contract->getStateVariables())
if (functionsSeen.count(v->getName()) == 0 && v->isPartOfExternalInterface())
@ -314,11 +387,11 @@ TypePointer EnumValue::getType(ContractDefinition const*) const
void InheritanceSpecifier::checkTypeRequirements()
{
m_baseName->checkTypeRequirements();
m_baseName->checkTypeRequirements(nullptr);
for (ASTPointer<Expression> const& argument: m_arguments)
argument->checkTypeRequirements();
argument->checkTypeRequirements(nullptr);
ContractDefinition const* base = dynamic_cast<ContractDefinition const*>(m_baseName->getReferencedDeclaration());
ContractDefinition const* base = dynamic_cast<ContractDefinition const*>(&m_baseName->getReferencedDeclaration());
solAssert(base, "Base contract not available.");
TypePointers parameterTypes = ContractType(*base).getConstructorType()->getParameterTypes();
if (!m_arguments.empty() && parameterTypes.size() != m_arguments.size())
@ -428,7 +501,8 @@ void VariableDeclaration::checkTypeRequirements()
if (!m_value)
// This feature might be extended in the future.
BOOST_THROW_EXCEPTION(createTypeError("Assignment necessary for type detection."));
m_value->checkTypeRequirements();
m_value->checkTypeRequirements(nullptr);
TypePointer type = m_value->getType();
if (type->getCategory() == Type::Category::IntegerConstant)
{
@ -468,18 +542,22 @@ void ModifierDefinition::checkTypeRequirements()
void ModifierInvocation::checkTypeRequirements(vector<ContractDefinition const*> const& _bases)
{
m_modifierName->checkTypeRequirements();
TypePointers argumentTypes;
for (ASTPointer<Expression> const& argument: m_arguments)
argument->checkTypeRequirements();
{
argument->checkTypeRequirements(nullptr);
argumentTypes.push_back(argument->getType());
}
m_modifierName->checkTypeRequirements(&argumentTypes);
auto declaration = m_modifierName->getReferencedDeclaration();
auto const* declaration = &m_modifierName->getReferencedDeclaration();
vector<ASTPointer<VariableDeclaration>> emptyParameterList;
vector<ASTPointer<VariableDeclaration>> const* parameters = nullptr;
if (auto modifier = dynamic_cast<ModifierDefinition const*>(declaration))
parameters = &modifier->getParameters();
else
// check parameters for Base constructors
for (auto const* base: _bases)
for (ContractDefinition const* base: _bases)
if (declaration == base)
{
if (auto referencedConstructor = base->getConstructor())
@ -563,9 +641,9 @@ void VariableDeclarationStatement::checkTypeRequirements()
m_variable->checkTypeRequirements();
}
void Assignment::checkTypeRequirements()
void Assignment::checkTypeRequirements(TypePointers const*)
{
m_leftHandSide->checkTypeRequirements();
m_leftHandSide->checkTypeRequirements(nullptr);
m_leftHandSide->requireLValue();
if (m_leftHandSide->getType()->getCategory() == Type::Category::Mapping)
BOOST_THROW_EXCEPTION(createTypeError("Mappings cannot be assigned to."));
@ -575,7 +653,7 @@ void Assignment::checkTypeRequirements()
else
{
// compound assignment
m_rightHandSide->checkTypeRequirements();
m_rightHandSide->checkTypeRequirements(nullptr);
TypePointer resultType = m_type->binaryOperatorResult(Token::AssignmentToBinaryOp(m_assigmentOperator),
m_rightHandSide->getType());
if (!resultType || *resultType != *m_type)
@ -588,7 +666,7 @@ void Assignment::checkTypeRequirements()
void ExpressionStatement::checkTypeRequirements()
{
m_expression->checkTypeRequirements();
m_expression->checkTypeRequirements(nullptr);
if (m_expression->getType()->getCategory() == Type::Category::IntegerConstant)
if (!dynamic_pointer_cast<IntegerConstantType const>(m_expression->getType())->getIntegerType())
BOOST_THROW_EXCEPTION(m_expression->createTypeError("Invalid integer constant."));
@ -596,7 +674,7 @@ void ExpressionStatement::checkTypeRequirements()
void Expression::expectType(Type const& _expectedType)
{
checkTypeRequirements();
checkTypeRequirements(nullptr);
Type const& type = *getType();
if (!type.isImplicitlyConvertibleTo(_expectedType))
BOOST_THROW_EXCEPTION(createTypeError("Type " + type.toString() +
@ -611,10 +689,10 @@ void Expression::requireLValue()
m_lvalueRequested = true;
}
void UnaryOperation::checkTypeRequirements()
void UnaryOperation::checkTypeRequirements(TypePointers const*)
{
// Inc, Dec, Add, Sub, Not, BitNot, Delete
m_subExpression->checkTypeRequirements();
m_subExpression->checkTypeRequirements(nullptr);
if (m_operator == Token::Value::Inc || m_operator == Token::Value::Dec || m_operator == Token::Value::Delete)
m_subExpression->requireLValue();
m_type = m_subExpression->getType()->unaryOperatorResult(m_operator);
@ -622,10 +700,10 @@ void UnaryOperation::checkTypeRequirements()
BOOST_THROW_EXCEPTION(createTypeError("Unary operator not compatible with type."));
}
void BinaryOperation::checkTypeRequirements()
void BinaryOperation::checkTypeRequirements(TypePointers const*)
{
m_left->checkTypeRequirements();
m_right->checkTypeRequirements();
m_left->checkTypeRequirements(nullptr);
m_right->checkTypeRequirements(nullptr);
m_commonType = m_left->getType()->binaryOperatorResult(m_operator, m_right->getType());
if (!m_commonType)
BOOST_THROW_EXCEPTION(createTypeError("Operator " + string(Token::toString(m_operator)) +
@ -635,11 +713,22 @@ void BinaryOperation::checkTypeRequirements()
m_type = Token::isCompareOp(m_operator) ? make_shared<BoolType>() : m_commonType;
}
void FunctionCall::checkTypeRequirements()
void FunctionCall::checkTypeRequirements(TypePointers const*)
{
m_expression->checkTypeRequirements();
bool isPositionalCall = m_names.empty();
// we need to check arguments' type first as they will be forwarded to
// m_expression->checkTypeRequirements
TypePointers argumentTypes;
for (ASTPointer<Expression> const& argument: m_arguments)
argument->checkTypeRequirements();
{
argument->checkTypeRequirements(nullptr);
// only store them for positional calls
if (isPositionalCall)
argumentTypes.push_back(argument->getType());
}
m_expression->checkTypeRequirements(isPositionalCall ? &argumentTypes : nullptr);
Type const* expressionType = m_expression->getType().get();
if (isTypeConversion())
@ -649,7 +738,7 @@ void FunctionCall::checkTypeRequirements()
// number of non-mapping members
if (m_arguments.size() != 1)
BOOST_THROW_EXCEPTION(createTypeError("More than one argument for explicit type conversion."));
if (!m_names.empty())
if (!isPositionalCall)
BOOST_THROW_EXCEPTION(createTypeError("Type conversion cannot allow named arguments."));
if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type.getActualType()))
BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed."));
@ -664,8 +753,9 @@ void FunctionCall::checkTypeRequirements()
if (!functionType->takesArbitraryParameters() && parameterTypes.size() != m_arguments.size())
BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call."));
if (m_names.empty())
if (isPositionalCall)
{
// call by positional arguments
for (size_t i = 0; i < m_arguments.size(); ++i)
if (!functionType->takesArbitraryParameters() &&
!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i]))
@ -673,6 +763,7 @@ void FunctionCall::checkTypeRequirements()
}
else
{
// call by named arguments
if (functionType->takesArbitraryParameters())
BOOST_THROW_EXCEPTION(createTypeError("Named arguments cannnot be used for functions "
"that take arbitrary parameters."));
@ -719,10 +810,10 @@ bool FunctionCall::isTypeConversion() const
return m_expression->getType()->getCategory() == Type::Category::TypeType;
}
void NewExpression::checkTypeRequirements()
void NewExpression::checkTypeRequirements(TypePointers const*)
{
m_contractName->checkTypeRequirements();
m_contract = dynamic_cast<ContractDefinition const*>(m_contractName->getReferencedDeclaration());
m_contractName->checkTypeRequirements(nullptr);
m_contract = dynamic_cast<ContractDefinition const*>(&m_contractName->getReferencedDeclaration());
if (!m_contract)
BOOST_THROW_EXCEPTION(createTypeError("Identifier is not a contract."));
if (!m_contract->isFullyImplemented())
@ -733,15 +824,37 @@ void NewExpression::checkTypeRequirements()
FunctionType::Location::Creation);
}
void MemberAccess::checkTypeRequirements()
void MemberAccess::checkTypeRequirements(TypePointers const* _argumentTypes)
{
m_expression->checkTypeRequirements();
m_expression->checkTypeRequirements(nullptr);
Type const& type = *m_expression->getType();
m_type = type.getMemberType(*m_memberName);
if (!m_type)
BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found or not "
"visible in " + type.toString()));
// This should probably move somewhere else.
MemberList::MemberMap possibleMembers = type.getMembers().membersByName(*m_memberName);
if (possibleMembers.size() > 1 && _argumentTypes)
{
// do override resolution
for (auto it = possibleMembers.begin(); it != possibleMembers.end();)
if (
it->type->getCategory() == Type::Category::Function &&
!dynamic_cast<FunctionType const&>(*it->type).canTakeArguments(*_argumentTypes)
)
it = possibleMembers.erase(it);
else
++it;
}
if (possibleMembers.size() == 0)
BOOST_THROW_EXCEPTION(createTypeError(
"Member \"" + *m_memberName + "\" not found or not visible "
"after argument-dependent lookup in " + type.toString()
));
else if (possibleMembers.size() > 1)
BOOST_THROW_EXCEPTION(createTypeError(
"Member \"" + *m_memberName + "\" not unique "
"after argument-dependent lookup in " + type.toString()
));
m_referencedDeclaration = possibleMembers.front().declaration;
m_type = possibleMembers.front().type;
if (type.getCategory() == Type::Category::Struct)
m_isLValue = true;
else if (type.getCategory() == Type::Category::Array)
@ -754,9 +867,9 @@ void MemberAccess::checkTypeRequirements()
m_isLValue = false;
}
void IndexAccess::checkTypeRequirements()
void IndexAccess::checkTypeRequirements(TypePointers const*)
{
m_base->checkTypeRequirements();
m_base->checkTypeRequirements(nullptr);
switch (m_base->getType()->getCategory())
{
case Type::Category::Array:
@ -789,7 +902,7 @@ void IndexAccess::checkTypeRequirements()
m_type = make_shared<TypeType>(make_shared<ArrayType>(ArrayType::Location::Memory, type.getActualType()));
else
{
m_index->checkTypeRequirements();
m_index->checkTypeRequirements(nullptr);
auto length = dynamic_cast<IntegerConstantType const*>(m_index->getType().get());
if (!length)
BOOST_THROW_EXCEPTION(m_index->createTypeError("Integer constant expected."));
@ -804,22 +917,57 @@ void IndexAccess::checkTypeRequirements()
}
}
void Identifier::checkTypeRequirements()
void Identifier::checkTypeRequirements(TypePointers const* _argumentTypes)
{
solAssert(m_referencedDeclaration, "Identifier not resolved.");
if (!m_referencedDeclaration)
{
if (!_argumentTypes)
BOOST_THROW_EXCEPTION(createTypeError("Unable to determine overloaded type."));
overloadResolution(*_argumentTypes);
}
solAssert(!!m_referencedDeclaration, "Referenced declaration is null after overload resolution.");
m_isLValue = m_referencedDeclaration->isLValue();
m_type = m_referencedDeclaration->getType(m_currentContract);
if (!m_type)
BOOST_THROW_EXCEPTION(createTypeError("Declaration referenced before type could be determined."));
}
void ElementaryTypeNameExpression::checkTypeRequirements()
Declaration const& Identifier::getReferencedDeclaration() const
{
solAssert(!!m_referencedDeclaration, "Identifier not resolved.");
return *m_referencedDeclaration;
}
void Identifier::overloadResolution(TypePointers const& _argumentTypes)
{
solAssert(!m_referencedDeclaration, "Referenced declaration should be null before overload resolution.");
solAssert(!m_overloadedDeclarations.empty(), "No candidates for overload resolution found.");
std::vector<Declaration const*> possibles;
if (m_overloadedDeclarations.size() == 1)
m_referencedDeclaration = *m_overloadedDeclarations.begin();
for (Declaration const* declaration: m_overloadedDeclarations)
{
TypePointer const& function = declaration->getType();
auto const* functionType = dynamic_cast<FunctionType const*>(function.get());
if (functionType && functionType->canTakeArguments(_argumentTypes))
possibles.push_back(declaration);
}
if (possibles.size() == 1)
m_referencedDeclaration = possibles.front();
else if (possibles.empty())
BOOST_THROW_EXCEPTION(createTypeError("No matching declaration found after argument-dependent lookup."));
else
BOOST_THROW_EXCEPTION(createTypeError("No unique declaration found after argument-dependent lookup."));
}
void ElementaryTypeNameExpression::checkTypeRequirements(TypePointers const*)
{
m_type = make_shared<TypeType>(Type::fromElementaryTypeName(m_typeToken));
}
void Literal::checkTypeRequirements()
void Literal::checkTypeRequirements(TypePointers const*)
{
m_type = Type::forLiteral(*this);
if (!m_type)

72
libsolidity/AST.h

@ -143,8 +143,8 @@ public:
ASTString const& getName() const { return *m_name; }
Visibility getVisibility() const { return m_visibility == Visibility::Default ? getDefaultVisibility() : m_visibility; }
bool isPublic() const { return getVisibility() >= Visibility::Public; }
bool isVisibleInContract() const { return getVisibility() != Visibility::External; }
virtual bool isVisibleInDerivedContracts() const { return isVisibleInContract() && getVisibility() >= Visibility::Internal; }
virtual bool isVisibleInContract() const { return getVisibility() != Visibility::External; }
bool isVisibleInDerivedContracts() const { return isVisibleInContract() && getVisibility() >= Visibility::Internal; }
/// @returns the scope this declaration resides in. Can be nullptr if it is the global scope.
/// Available only after name and type resolution step.
@ -156,7 +156,7 @@ public:
/// contract types.
virtual TypePointer getType(ContractDefinition const* m_currentContract = nullptr) const = 0;
virtual bool isLValue() const { return false; }
virtual bool isPartOfExternalInterface() const { return false; };
virtual bool isPartOfExternalInterface() const { return false; }
protected:
virtual Visibility getDefaultVisibility() const { return Visibility::Public; }
@ -282,9 +282,15 @@ public:
FunctionDefinition const* getFallbackFunction() const;
private:
/// Checks that two functions defined in this contract with the same name have different
/// arguments and that there is at most one constructor.
void checkDuplicateFunctions() const;
void checkIllegalOverrides() const;
void checkAbstractFunctions();
void checkAbstractConstructors();
/// Checks that different functions with external visibility end up having different
/// external argument types (i.e. different signature).
void checkExternalTypeClashes() const;
std::vector<std::pair<FixedHash<4>, FunctionTypePointer>> const& getInterfaceFunctionList() const;
@ -437,10 +443,9 @@ public:
ASTPointer<ParameterList> const& getReturnParameterList() const { return m_returnParameters; }
Block const& getBody() const { return *m_body; }
virtual bool isVisibleInDerivedContracts() const override
virtual bool isVisibleInContract() const override
{
return !isConstructor() && !getName().empty() && isVisibleInContract() &&
getVisibility() >= Visibility::Internal;
return Declaration::isVisibleInContract() && !isConstructor() && !getName().empty();
}
virtual TypePointer getType(ContractDefinition const*) const override;
virtual bool isPartOfExternalInterface() const override { return isPublic() && !m_isConstructor && !getName().empty(); }
@ -968,7 +973,10 @@ class Expression: public ASTNode
{
public:
Expression(SourceLocation const& _location): ASTNode(_location) {}
virtual void checkTypeRequirements() = 0;
/// Performs type checking after which m_type should be set.
/// @arg _argumentTypes if set, provides the argument types for the case that this expression
/// is used in the context of a call, used for function overload resolution.
virtual void checkTypeRequirements(TypePointers const* _argumentTypes) = 0;
std::shared_ptr<Type const> const& getType() const { return m_type; }
bool isLValue() const { return m_isLValue; }
@ -1007,7 +1015,7 @@ public:
}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
virtual void checkTypeRequirements() override;
virtual void checkTypeRequirements(TypePointers const* _argumentTypes) override;
Expression const& getLeftHandSide() const { return *m_leftHandSide; }
Token::Value getAssignmentOperator() const { return m_assigmentOperator; }
@ -1035,7 +1043,7 @@ public:
}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
virtual void checkTypeRequirements() override;
virtual void checkTypeRequirements(TypePointers const* _argumentTypes) override;
Token::Value getOperator() const { return m_operator; }
bool isPrefixOperation() const { return m_isPrefix; }
@ -1062,7 +1070,7 @@ public:
}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
virtual void checkTypeRequirements() override;
virtual void checkTypeRequirements(TypePointers const* _argumentTypes) override;
Expression const& getLeftExpression() const { return *m_left; }
Expression const& getRightExpression() const { return *m_right; }
@ -1090,7 +1098,7 @@ public:
Expression(_location), m_expression(_expression), m_arguments(_arguments), m_names(_names) {}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
virtual void checkTypeRequirements() override;
virtual void checkTypeRequirements(TypePointers const* _argumentTypes) override;
Expression const& getExpression() const { return *m_expression; }
std::vector<ASTPointer<Expression const>> getArguments() const { return {m_arguments.begin(), m_arguments.end()}; }
@ -1116,7 +1124,7 @@ public:
Expression(_location), m_contractName(_contractName) {}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
virtual void checkTypeRequirements() override;
virtual void checkTypeRequirements(TypePointers const* _argumentTypes) override;
/// Returns the referenced contract. Can only be called after type checking.
ContractDefinition const* getContract() const { solAssert(m_contract, ""); return m_contract; }
@ -1140,11 +1148,18 @@ public:
virtual void accept(ASTConstVisitor& _visitor) const override;
Expression const& getExpression() const { return *m_expression; }
ASTString const& getMemberName() const { return *m_memberName; }
virtual void checkTypeRequirements() override;
/// @returns the declaration referenced by this expression. Might return nullptr even if the
/// expression is valid, e.g. if the member does not correspond to an AST node.
Declaration const* referencedDeclaration() const { return m_referencedDeclaration; }
virtual void checkTypeRequirements(TypePointers const* _argumentTypes) override;
private:
ASTPointer<Expression> m_expression;
ASTPointer<ASTString> m_memberName;
/// Pointer to the referenced declaration, this is sometimes needed to resolve function over
/// loads in the type-checking phase.
Declaration const* m_referencedDeclaration = nullptr;
};
/**
@ -1158,7 +1173,7 @@ public:
Expression(_location), m_base(_base), m_index(_index) {}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
virtual void checkTypeRequirements() override;
virtual void checkTypeRequirements(TypePointers const* _argumentTypes) override;
Expression const& getBaseExpression() const { return *m_base; }
Expression const* getIndexExpression() const { return m_index.get(); }
@ -1188,18 +1203,31 @@ public:
PrimaryExpression(_location), m_name(_name) {}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
virtual void checkTypeRequirements() override;
virtual void checkTypeRequirements(TypePointers const* _argumentTypes) override;
ASTString const& getName() const { return *m_name; }
void setReferencedDeclaration(Declaration const& _referencedDeclaration,
ContractDefinition const* _currentContract = nullptr)
void setReferencedDeclaration(
Declaration const& _referencedDeclaration,
ContractDefinition const* _currentContract = nullptr
)
{
m_referencedDeclaration = &_referencedDeclaration;
m_currentContract = _currentContract;
}
Declaration const* getReferencedDeclaration() const { return m_referencedDeclaration; }
ContractDefinition const* getCurrentContract() const { return m_currentContract; }
Declaration const& getReferencedDeclaration() const;
/// Stores a set of possible declarations referenced by this identifier. Has to be resolved
/// providing argument types using overloadResolution before the referenced declaration
/// is accessed.
void setOverloadedDeclarations(std::set<Declaration const*> const& _declarations)
{
m_overloadedDeclarations = _declarations;
}
/// Tries to find exactly one of the possible referenced declarations provided the given
/// argument types in a call context.
void overloadResolution(TypePointers const& _argumentTypes);
private:
ASTPointer<ASTString> m_name;
@ -1209,6 +1237,8 @@ private:
/// Stores a reference to the current contract. This is needed because types of base contracts
/// change depending on the context.
ContractDefinition const* m_currentContract = nullptr;
/// A set of overloaded declarations, right now only FunctionDefinition has overloaded declarations.
std::set<Declaration const*> m_overloadedDeclarations;
};
/**
@ -1226,7 +1256,7 @@ public:
}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
virtual void checkTypeRequirements() override;
virtual void checkTypeRequirements(TypePointers const* _argumentTypes) override;
Token::Value getTypeToken() const { return m_typeToken; }
@ -1260,7 +1290,7 @@ public:
PrimaryExpression(_location), m_token(_token), m_value(_value), m_subDenomination(_sub) {}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
virtual void checkTypeRequirements() override;
virtual void checkTypeRequirements(TypePointers const* _argumentTypes) override;
Token::Value getToken() const { return m_token; }
/// @returns the non-parsed value of the literal

6
libsolidity/Compiler.cpp

@ -90,7 +90,7 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract, Comp
for (auto const& modifier: constructor->getModifiers())
{
auto baseContract = dynamic_cast<ContractDefinition const*>(
modifier->getName()->getReferencedDeclaration());
&modifier->getName()->getReferencedDeclaration());
if (baseContract)
if (m_baseArguments.count(baseContract->getConstructor()) == 0)
m_baseArguments[baseContract->getConstructor()] = &modifier->getArguments();
@ -99,7 +99,7 @@ void Compiler::packIntoContractCreator(ContractDefinition const& _contract, Comp
for (ASTPointer<InheritanceSpecifier> const& base: contract->getBaseContracts())
{
ContractDefinition const* baseContract = dynamic_cast<ContractDefinition const*>(
base->getName()->getReferencedDeclaration());
&base->getName()->getReferencedDeclaration());
solAssert(baseContract, "");
if (m_baseArguments.count(baseContract->getConstructor()) == 0)
@ -542,7 +542,7 @@ void Compiler::appendModifierOrFunctionCode()
ASTPointer<ModifierInvocation> const& modifierInvocation = m_currentFunction->getModifiers()[m_modifierDepth];
// constructor call should be excluded
if (dynamic_cast<ContractDefinition const*>(modifierInvocation->getName()->getReferencedDeclaration()))
if (dynamic_cast<ContractDefinition const*>(&modifierInvocation->getName()->getReferencedDeclaration()))
{
++m_modifierDepth;
appendModifierOrFunctionCode();

38
libsolidity/CompilerContext.cpp

@ -102,23 +102,13 @@ eth::AssemblyItem CompilerContext::getFunctionEntryLabel(Declaration const& _dec
eth::AssemblyItem CompilerContext::getVirtualFunctionEntryLabel(FunctionDefinition const& _function)
{
solAssert(!m_inheritanceHierarchy.empty(), "No inheritance hierarchy set.");
for (ContractDefinition const* contract: m_inheritanceHierarchy)
for (ASTPointer<FunctionDefinition> const& function: contract->getDefinedFunctions())
if (!function->isConstructor() && function->getName() == _function.getName())
return getFunctionEntryLabel(*function);
solAssert(false, "Virtual function " + _function.getName() + " not found.");
return m_asm.newTag(); // not reached
return getVirtualFunctionEntryLabel(_function, m_inheritanceHierarchy.begin());
}
eth::AssemblyItem CompilerContext::getSuperFunctionEntryLabel(string const& _name, ContractDefinition const& _base)
eth::AssemblyItem CompilerContext::getSuperFunctionEntryLabel(FunctionDefinition const& _function, ContractDefinition const& _base)
{
auto it = getSuperContract(_base);
for (; it != m_inheritanceHierarchy.end(); ++it)
for (ASTPointer<FunctionDefinition> const& function: (*it)->getDefinedFunctions())
if (!function->isConstructor() && function->getName() == _name)
return getFunctionEntryLabel(*function);
solAssert(false, "Super function " + _name + " not found.");
return m_asm.newTag(); // not reached
solAssert(!m_inheritanceHierarchy.empty(), "No inheritance hierarchy set.");
return getVirtualFunctionEntryLabel(_function, getSuperContract(_base));
}
FunctionDefinition const* CompilerContext::getNextConstructor(ContractDefinition const& _contract) const
@ -190,6 +180,26 @@ void CompilerContext::resetVisitedNodes(ASTNode const* _node)
updateSourceLocation();
}
eth::AssemblyItem CompilerContext::getVirtualFunctionEntryLabel(
FunctionDefinition const& _function,
vector<ContractDefinition const*>::const_iterator _searchStart
)
{
string name = _function.getName();
FunctionType functionType(_function);
auto it = _searchStart;
for (; it != m_inheritanceHierarchy.end(); ++it)
for (ASTPointer<FunctionDefinition> const& function: (*it)->getDefinedFunctions())
if (
function->getName() == name &&
!function->isConstructor() &&
FunctionType(*function).hasEqualArgumentTypes(functionType)
)
return getFunctionEntryLabel(*function);
solAssert(false, "Super function " + name + " not found.");
return m_asm.newTag(); // not reached
}
vector<ContractDefinition const*>::const_iterator CompilerContext::getSuperContract(ContractDefinition const& _contract) const
{
solAssert(!m_inheritanceHierarchy.empty(), "No inheritance hierarchy set.");

11
libsolidity/CompilerContext.h

@ -63,9 +63,9 @@ public:
void setInheritanceHierarchy(std::vector<ContractDefinition const*> const& _hierarchy) { m_inheritanceHierarchy = _hierarchy; }
/// @returns the entry label of the given function and takes overrides into account.
eth::AssemblyItem getVirtualFunctionEntryLabel(FunctionDefinition const& _function);
/// @returns the entry label of function with the given name from the most derived class just
/// @returns the entry label of a function that overrides the given declaration from the most derived class just
/// above _base in the current inheritance hierarchy.
eth::AssemblyItem getSuperFunctionEntryLabel(std::string const& _name, ContractDefinition const& _base);
eth::AssemblyItem getSuperFunctionEntryLabel(FunctionDefinition const& _function, ContractDefinition const& _base);
FunctionDefinition const* getNextConstructor(ContractDefinition const& _contract) const;
/// @returns the set of functions for which we still need to generate code
@ -141,6 +141,13 @@ public:
};
private:
/// @returns the entry label of the given function - searches the inheritance hierarchy
/// startig from the given point towards the base.
eth::AssemblyItem getVirtualFunctionEntryLabel(
FunctionDefinition const& _function,
std::vector<ContractDefinition const*>::const_iterator _searchStart
);
/// @returns an iterator to the contract directly above the given contract.
std::vector<ContractDefinition const*>::const_iterator getSuperContract(const ContractDefinition &_contract) const;
/// Updates source location set in the assembly.
void updateSourceLocation();

40
libsolidity/DeclarationContainer.cpp

@ -22,11 +22,11 @@
#include <libsolidity/DeclarationContainer.h>
#include <libsolidity/AST.h>
#include <libsolidity/Types.h>
namespace dev
{
namespace solidity
{
using namespace std;
using namespace dev;
using namespace dev::solidity;
bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, bool _invisible, bool _update)
{
@ -34,17 +34,34 @@ bool DeclarationContainer::registerDeclaration(Declaration const& _declaration,
if (name.empty())
return true;
if (!_update && (m_declarations.count(name) || m_invisibleDeclarations.count(name)))
return false;
if (_update)
{
solAssert(!dynamic_cast<FunctionDefinition const*>(&_declaration), "Attempt to update function definition.");
m_declarations[name].clear();
m_invisibleDeclarations[name].clear();
}
else
{
if (dynamic_cast<FunctionDefinition const*>(&_declaration))
{
// check that all other declarations with the same name are functions
for (auto&& declaration: m_invisibleDeclarations[name] + m_declarations[name])
if (!dynamic_cast<FunctionDefinition const*>(declaration))
return false;
}
else if (m_declarations.count(name) > 0 || m_invisibleDeclarations.count(name) > 0)
return false;
}
if (_invisible)
m_invisibleDeclarations.insert(name);
m_invisibleDeclarations[name].insert(&_declaration);
else
m_declarations[name] = &_declaration;
m_declarations[name].insert(&_declaration);
return true;
}
Declaration const* DeclarationContainer::resolveName(ASTString const& _name, bool _recursive) const
set<Declaration const*> DeclarationContainer::resolveName(ASTString const& _name, bool _recursive) const
{
solAssert(!_name.empty(), "Attempt to resolve empty name.");
auto result = m_declarations.find(_name);
@ -52,8 +69,5 @@ Declaration const* DeclarationContainer::resolveName(ASTString const& _name, boo
return result->second;
if (_recursive && m_enclosingContainer)
return m_enclosingContainer->resolveName(_name, true);
return nullptr;
}
}
return set<Declaration const*>({});
}

8
libsolidity/DeclarationContainer.h

@ -48,15 +48,15 @@ public:
/// @param _update if true, replaces a potential declaration that is already present
/// @returns false if the name was already declared.
bool registerDeclaration(Declaration const& _declaration, bool _invisible = false, bool _update = false);
Declaration const* resolveName(ASTString const& _name, bool _recursive = false) const;
std::set<Declaration const*> resolveName(ASTString const& _name, bool _recursive = false) const;
Declaration const* getEnclosingDeclaration() const { return m_enclosingDeclaration; }
std::map<ASTString, Declaration const*> const& getDeclarations() const { return m_declarations; }
std::map<ASTString, std::set<Declaration const*>> const& getDeclarations() const { return m_declarations; }
private:
Declaration const* m_enclosingDeclaration;
DeclarationContainer const* m_enclosingContainer;
std::map<ASTString, Declaration const*> m_declarations;
std::set<ASTString> m_invisibleDeclarations;
std::map<ASTString, std::set<Declaration const*>> m_declarations;
std::map<ASTString, std::set<Declaration const*>> m_invisibleDeclarations;
};
}

47
libsolidity/ExpressionCompiler.cpp

@ -626,13 +626,25 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
bool alsoSearchInteger = false;
ContractType const& type = dynamic_cast<ContractType const&>(*_memberAccess.getExpression().getType());
if (type.isSuper())
m_context << m_context.getSuperFunctionEntryLabel(member, type.getContractDefinition()).pushTag();
{
solAssert(!!_memberAccess.referencedDeclaration(), "Referenced declaration not resolved.");
m_context << m_context.getSuperFunctionEntryLabel(
dynamic_cast<FunctionDefinition const&>(*_memberAccess.referencedDeclaration()),
type.getContractDefinition()
).pushTag();
}
else
{
// ordinary contract type
u256 identifier = type.getFunctionIdentifier(member);
if (identifier != Invalid256)
if (Declaration const* declaration = _memberAccess.referencedDeclaration())
{
u256 identifier;
if (auto const* variable = dynamic_cast<VariableDeclaration const*>(declaration))
identifier = FunctionType(*variable).externalIdentifier();
else if (auto const* function = dynamic_cast<FunctionDefinition const*>(declaration))
identifier = FunctionType(*function).externalIdentifier();
else
solAssert(false, "Contract member is neither variable nor function.");
appendTypeConversion(type, IntegerType(0, IntegerType::Modifier::Address), true);
m_context << identifier;
}
@ -708,19 +720,16 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
case Type::Category::TypeType:
{
TypeType const& type = dynamic_cast<TypeType const&>(*_memberAccess.getExpression().getType());
if (!type.getMembers().getMemberType(member))
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to " + type.toString()));
solAssert(
!type.getMembers().membersByName(_memberAccess.getMemberName()).empty(),
"Invalid member access to " + type.toString()
);
if (auto contractType = dynamic_cast<ContractType const*>(type.getActualType().get()))
if (dynamic_cast<ContractType const*>(type.getActualType().get()))
{
ContractDefinition const& contract = contractType->getContractDefinition();
for (ASTPointer<FunctionDefinition> const& function: contract.getDefinedFunctions())
if (function->getName() == member)
{
m_context << m_context.getFunctionEntryLabel(*function).pushTag();
return;
}
solAssert(false, "Function not found in member access.");
auto const* function = dynamic_cast<FunctionDefinition const*>(_memberAccess.referencedDeclaration());
solAssert(!!function, "Function not found in member access");
m_context << m_context.getFunctionEntryLabel(*function).pushTag();
}
else if (auto enumType = dynamic_cast<EnumType const*>(type.getActualType().get()))
m_context << enumType->getMemberValue(_memberAccess.getMemberName());
@ -805,7 +814,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
void ExpressionCompiler::endVisit(Identifier const& _identifier)
{
CompilerContext::LocationSetter locationSetter(m_context, _identifier);
Declaration const* declaration = _identifier.getReferencedDeclaration();
Declaration const* declaration = &_identifier.getReferencedDeclaration();
if (MagicVariableDeclaration const* magicVar = dynamic_cast<MagicVariableDeclaration const*>(declaration))
{
switch (magicVar->getType()->getCategory())
@ -1066,7 +1075,13 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio
m_context << eth::Instruction::POP;
m_context << eth::Instruction::POP; // pop contract address
if (firstType)
if (_functionType.getLocation() == FunctionType::Location::RIPEMD160)
{
// fix: built-in contract returns right-aligned data
CompilerUtils(m_context).loadFromMemory(0, IntegerType(160), false, true);
appendTypeConversion(IntegerType(160), FixedBytesType(20));
}
else if (firstType)
CompilerUtils(m_context).loadFromMemory(0, *firstType, false, true);
}

8
libsolidity/LValue.cpp

@ -193,10 +193,10 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
for (auto const& member: structType.getMembers())
{
// assign each member that is not a mapping
TypePointer const& memberType = member.second;
TypePointer const& memberType = member.type;
if (memberType->getCategory() == Type::Category::Mapping)
continue;
pair<u256, unsigned> const& offsets = structType.getStorageOffsetsOfMember(member.first);
pair<u256, unsigned> const& offsets = structType.getStorageOffsetsOfMember(member.name);
m_context
<< offsets.first << u256(offsets.second)
<< eth::Instruction::DUP6 << eth::Instruction::DUP3
@ -247,10 +247,10 @@ void StorageItem::setToZero(SourceLocation const&, bool _removeReference) const
for (auto const& member: structType.getMembers())
{
// zero each member that is not a mapping
TypePointer const& memberType = member.second;
TypePointer const& memberType = member.type;
if (memberType->getCategory() == Type::Category::Mapping)
continue;
pair<u256, unsigned> const& offsets = structType.getStorageOffsetsOfMember(member.first);
pair<u256, unsigned> const& offsets = structType.getStorageOffsetsOfMember(member.name);
m_context
<< offsets.first << eth::Instruction::DUP3 << eth::Instruction::ADD
<< u256(offsets.second);

123
libsolidity/NameAndTypeResolver.cpp

@ -31,7 +31,7 @@ namespace dev
namespace solidity
{
NameAndTypeResolver::NameAndTypeResolver(std::vector<Declaration const*> const& _globals)
NameAndTypeResolver::NameAndTypeResolver(vector<Declaration const*> const& _globals)
{
for (Declaration const* declaration: _globals)
m_scopes[nullptr].registerDeclaration(*declaration);
@ -53,8 +53,9 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
m_currentScope = &m_scopes[&_contract];
linearizeBaseContracts(_contract);
// we first import non-functions only as we do not yet know the argument types
for (ContractDefinition const* base: _contract.getLinearizedBaseContracts())
importInheritedScope(*base);
importInheritedScope(*base, false); // import non-functions
for (ASTPointer<StructDefinition> const& structDef: _contract.getDefinedStructs())
ReferencesResolver resolver(*structDef, *this, &_contract, nullptr);
@ -64,6 +65,8 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
ReferencesResolver resolver(*variable, *this, &_contract, nullptr);
for (ASTPointer<EventDefinition> const& event: _contract.getEvents())
ReferencesResolver resolver(*event, *this, &_contract, nullptr);
// these can contain code, only resolve parameters for now
for (ASTPointer<ModifierDefinition> const& modifier: _contract.getFunctionModifiers())
{
m_currentScope = &m_scopes[modifier.get()];
@ -75,6 +78,28 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
ReferencesResolver referencesResolver(*function, *this, &_contract,
function->getReturnParameterList().get());
}
m_currentScope = &m_scopes[&_contract];
for (ContractDefinition const* base: _contract.getLinearizedBaseContracts())
importInheritedScope(*base, true); // import functions
// now resolve references inside the code
for (ASTPointer<ModifierDefinition> const& modifier: _contract.getFunctionModifiers())
{
m_currentScope = &m_scopes[modifier.get()];
ReferencesResolver resolver(*modifier, *this, &_contract, nullptr, true);
}
for (ASTPointer<FunctionDefinition> const& function: _contract.getDefinedFunctions())
{
m_currentScope = &m_scopes[function.get()];
ReferencesResolver referencesResolver(
*function,
*this,
&_contract,
function->getReturnParameterList().get(),
true
);
}
}
void NameAndTypeResolver::checkTypeRequirements(ContractDefinition& _contract)
@ -90,31 +115,51 @@ void NameAndTypeResolver::updateDeclaration(Declaration const& _declaration)
solAssert(_declaration.getScope() == nullptr, "Updated declaration outside global scope.");
}
Declaration const* NameAndTypeResolver::resolveName(ASTString const& _name, Declaration const* _scope) const
set<Declaration const*> NameAndTypeResolver::resolveName(ASTString const& _name, Declaration const* _scope) const
{
auto iterator = m_scopes.find(_scope);
if (iterator == end(m_scopes))
return nullptr;
return set<Declaration const*>({});
return iterator->second.resolveName(_name, false);
}
Declaration const* NameAndTypeResolver::getNameFromCurrentScope(ASTString const& _name, bool _recursive)
set<Declaration const*> NameAndTypeResolver::getNameFromCurrentScope(ASTString const& _name, bool _recursive)
{
return m_currentScope->resolveName(_name, _recursive);
}
void NameAndTypeResolver::importInheritedScope(ContractDefinition const& _base)
void NameAndTypeResolver::importInheritedScope(ContractDefinition const& _base, bool _importFunctions)
{
auto iterator = m_scopes.find(&_base);
solAssert(iterator != end(m_scopes), "");
for (auto const& nameAndDeclaration: iterator->second.getDeclarations())
{
Declaration const* declaration = nameAndDeclaration.second;
// Import if it was declared in the base, is not the constructor and is visible in derived classes
if (declaration->getScope() == &_base && declaration->getName() != _base.getName() &&
declaration->isVisibleInDerivedContracts())
m_currentScope->registerDeclaration(*declaration);
}
for (auto const& declaration: nameAndDeclaration.second)
// Import if it was declared in the base, is not the constructor and is visible in derived classes
if (declaration->getScope() == &_base && declaration->isVisibleInDerivedContracts())
{
auto function = dynamic_cast<FunctionDefinition const*>(declaration);
if ((function == nullptr) == _importFunctions)
continue;
if (!!function)
{
FunctionType functionType(*function);
// only import if a function with the same arguments does not exist yet
bool functionWithEqualArgumentsFound = false;
for (auto knownDeclaration: m_currentScope->resolveName(nameAndDeclaration.first))
{
auto knownFunction = dynamic_cast<FunctionDefinition const*>(knownDeclaration);
if (!knownFunction)
continue; // this is not legal, but will be caught later
if (!FunctionType(*knownFunction).hasEqualArgumentTypes(functionType))
continue;
functionWithEqualArgumentsFound = true;
break;
}
if (functionWithEqualArgumentsFound)
continue;
}
m_currentScope->registerDeclaration(*declaration);
}
}
void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract) const
@ -125,8 +170,7 @@ void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract)
for (ASTPointer<InheritanceSpecifier> const& baseSpecifier: _contract.getBaseContracts())
{
ASTPointer<Identifier> baseName = baseSpecifier->getName();
ContractDefinition const* base = dynamic_cast<ContractDefinition const*>(
baseName->getReferencedDeclaration());
auto base = dynamic_cast<ContractDefinition const*>(&baseName->getReferencedDeclaration());
if (!base)
BOOST_THROW_EXCEPTION(baseName->createTypeError("Contract expected."));
// "push_front" has the effect that bases mentioned later can overwrite members of bases
@ -318,11 +362,19 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio
enterNewSubScope(_declaration);
}
ReferencesResolver::ReferencesResolver(ASTNode& _root, NameAndTypeResolver& _resolver,
ContractDefinition const* _currentContract,
ParameterList const* _returnParameters, bool _allowLazyTypes):
m_resolver(_resolver), m_currentContract(_currentContract),
m_returnParameters(_returnParameters), m_allowLazyTypes(_allowLazyTypes)
ReferencesResolver::ReferencesResolver(
ASTNode& _root,
NameAndTypeResolver& _resolver,
ContractDefinition const* _currentContract,
ParameterList const* _returnParameters,
bool _resolveInsideCode,
bool _allowLazyTypes
):
m_resolver(_resolver),
m_currentContract(_currentContract),
m_returnParameters(_returnParameters),
m_resolveInsideCode(_resolveInsideCode),
m_allowLazyTypes(_allowLazyTypes)
{
_root.accept(*this);
}
@ -361,24 +413,37 @@ bool ReferencesResolver::visit(Mapping&)
bool ReferencesResolver::visit(UserDefinedTypeName& _typeName)
{
Declaration const* declaration = m_resolver.getNameFromCurrentScope(_typeName.getName());
if (!declaration)
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_typeName.getLocation())
<< errinfo_comment("Undeclared identifier."));
_typeName.setReferencedDeclaration(*declaration);
auto declarations = m_resolver.getNameFromCurrentScope(_typeName.getName());
if (declarations.empty())
BOOST_THROW_EXCEPTION(
DeclarationError() <<
errinfo_sourceLocation(_typeName.getLocation()) <<
errinfo_comment("Undeclared identifier.")
);
else if (declarations.size() > 1)
BOOST_THROW_EXCEPTION(
DeclarationError() <<
errinfo_sourceLocation(_typeName.getLocation()) <<
errinfo_comment("Duplicate identifier.")
);
else
_typeName.setReferencedDeclaration(**declarations.begin());
return false;
}
bool ReferencesResolver::visit(Identifier& _identifier)
{
Declaration const* declaration = m_resolver.getNameFromCurrentScope(_identifier.getName());
if (!declaration)
auto declarations = m_resolver.getNameFromCurrentScope(_identifier.getName());
if (declarations.empty())
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_identifier.getLocation())
<< errinfo_comment("Undeclared identifier."));
_identifier.setReferencedDeclaration(*declaration, m_currentContract);
else if (declarations.size() == 1)
_identifier.setReferencedDeclaration(**declarations.begin(), m_currentContract);
else
// Duplicate declaration will be checked in checkTypeRequirements()
_identifier.setOverloadedDeclarations(declarations);
return false;
}
}
}

25
libsolidity/NameAndTypeResolver.h

@ -56,18 +56,19 @@ public:
/// Resolves the given @a _name inside the scope @a _scope. If @a _scope is omitted,
/// the global scope is used (i.e. the one containing only the contract).
/// @returns a pointer to the declaration on success or nullptr on failure.
Declaration const* resolveName(ASTString const& _name, Declaration const* _scope = nullptr) const;
std::set<Declaration const*> resolveName(ASTString const& _name, Declaration const* _scope = nullptr) const;
/// Resolves a name in the "current" scope. Should only be called during the initial
/// resolving phase.
Declaration const* getNameFromCurrentScope(ASTString const& _name, bool _recursive = true);
std::set<Declaration const*> getNameFromCurrentScope(ASTString const& _name, bool _recursive = true);
private:
void reset();
/// Imports all members declared directly in the given contract (i.e. does not import inherited
/// members) into the current scope if they are not present already.
void importInheritedScope(ContractDefinition const& _base);
/// Either imports all non-function members or all function members declared directly in the
/// given contract (i.e. does not import inherited members) into the current scope if they are
///not present already.
void importInheritedScope(ContractDefinition const& _base, bool _importFunctions);
/// Computes "C3-Linearization" of base contracts and stores it inside the contract.
void linearizeBaseContracts(ContractDefinition& _contract) const;
@ -126,13 +127,18 @@ private:
class ReferencesResolver: private ASTVisitor
{
public:
ReferencesResolver(ASTNode& _root, NameAndTypeResolver& _resolver,
ContractDefinition const* _currentContract,
ParameterList const* _returnParameters,
bool _allowLazyTypes = true);
ReferencesResolver(
ASTNode& _root,
NameAndTypeResolver& _resolver,
ContractDefinition const* _currentContract,
ParameterList const* _returnParameters,
bool _resolveInsideCode = false,
bool _allowLazyTypes = true
);
private:
virtual void endVisit(VariableDeclaration& _variable) override;
virtual bool visit(Block&) override { return m_resolveInsideCode; }
virtual bool visit(Identifier& _identifier) override;
virtual bool visit(UserDefinedTypeName& _typeName) override;
virtual bool visit(Mapping&) override;
@ -141,6 +147,7 @@ private:
NameAndTypeResolver& m_resolver;
ContractDefinition const* m_currentContract;
ParameterList const* m_returnParameters;
bool m_resolveInsideCode;
bool m_allowLazyTypes;
};

125
libsolidity/Types.cpp

@ -25,6 +25,7 @@
#include <boost/range/adaptor/reversed.hpp>
#include <libdevcore/CommonIO.h>
#include <libdevcore/CommonData.h>
#include <libdevcrypto/SHA3.h>
#include <libsolidity/Utils.h>
#include <libsolidity/AST.h>
@ -92,13 +93,13 @@ std::pair<u256, unsigned> const* MemberList::getMemberStorageOffset(string const
{
TypePointers memberTypes;
memberTypes.reserve(m_memberTypes.size());
for (auto const& nameAndType: m_memberTypes)
memberTypes.push_back(nameAndType.second);
for (auto const& member: m_memberTypes)
memberTypes.push_back(member.type);
m_storageOffsets.reset(new StorageOffsets());
m_storageOffsets->computeOffsets(memberTypes);
}
for (size_t index = 0; index < m_memberTypes.size(); ++index)
if (m_memberTypes[index].first == _name)
if (m_memberTypes[index].name == _name)
return m_storageOffsets->getOffset(index);
return nullptr;
}
@ -189,7 +190,7 @@ TypePointer Type::fromArrayTypeName(TypeName& _baseTypeName, Expression* _length
if (_length)
{
if (!_length->getType())
_length->checkTypeRequirements();
_length->checkTypeRequirements(nullptr);
auto const* length = dynamic_cast<IntegerConstantType const*>(_length->getType().get());
if (!length)
BOOST_THROW_EXCEPTION(_length->createTypeError("Invalid array length."));
@ -793,18 +794,46 @@ MemberList const& ContractType::getMembers() const
if (!m_members)
{
// All address members and all interface functions
vector<pair<string, TypePointer>> members(IntegerType::AddressMemberList.begin(),
IntegerType::AddressMemberList.end());
MemberList::MemberMap members(
IntegerType::AddressMemberList.begin(),
IntegerType::AddressMemberList.end()
);
if (m_super)
{
// add the most derived of all functions which are visible in derived contracts
for (ContractDefinition const* base: m_contract.getLinearizedBaseContracts())
for (ASTPointer<FunctionDefinition> const& function: base->getDefinedFunctions())
if (function->isVisibleInDerivedContracts())
members.push_back(make_pair(function->getName(), make_shared<FunctionType>(*function, true)));
{
if (!function->isVisibleInDerivedContracts())
continue;
auto functionType = make_shared<FunctionType>(*function, true);
bool functionWithEqualArgumentsFound = false;
for (auto const& member: members)
{
if (member.name != function->getName())
continue;
auto memberType = dynamic_cast<FunctionType const*>(member.type.get());
solAssert(!!memberType, "Override changes type.");
if (!memberType->hasEqualArgumentTypes(*functionType))
continue;
functionWithEqualArgumentsFound = true;
break;
}
if (!functionWithEqualArgumentsFound)
members.push_back(MemberList::Member(
function->getName(),
functionType,
function.get()
));
}
}
else
for (auto const& it: m_contract.getInterfaceFunctions())
members.push_back(make_pair(it.second->getDeclaration().getName(), it.second));
members.push_back(MemberList::Member(
it.second->getDeclaration().getName(),
it.second,
&it.second->getDeclaration()
));
m_members.reset(new MemberList(members));
}
return *m_members;
@ -823,16 +852,6 @@ shared_ptr<FunctionType const> const& ContractType::getConstructorType() const
return m_constructorType;
}
u256 ContractType::getFunctionIdentifier(string const& _functionName) const
{
auto interfaceFunctions = m_contract.getInterfaceFunctions();
for (auto const& it: m_contract.getInterfaceFunctions())
if (it.second->getDeclaration().getName() == _functionName)
return FixedHash<4>::Arith(it.first);
return Invalid256;
}
vector<tuple<VariableDeclaration const*, u256, unsigned>> ContractType::getStateVariables() const
{
vector<VariableDeclaration const*> variables;
@ -873,8 +892,8 @@ u256 StructType::getStorageSize() const
bool StructType::canLiveOutsideStorage() const
{
for (pair<string, TypePointer> const& member: getMembers())
if (!member.second->canLiveOutsideStorage())
for (auto const& member: getMembers())
if (!member.type->canLiveOutsideStorage())
return false;
return true;
}
@ -891,7 +910,7 @@ MemberList const& StructType::getMembers() const
{
MemberList::MemberMap members;
for (ASTPointer<VariableDeclaration> const& variable: m_struct.getMembers())
members.push_back(make_pair(variable->getName(), variable->getType()));
members.push_back(MemberList::Member(variable->getName(), variable->getType(), variable.get()));
m_members.reset(new MemberList(members));
}
return *m_members;
@ -1007,11 +1026,11 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
vector<string> retParamNames;
if (auto structType = dynamic_cast<StructType const*>(returnType.get()))
{
for (pair<string, TypePointer> const& member: structType->getMembers())
if (member.second->getCategory() != Category::Mapping && member.second->getCategory() != Category::Array)
for (auto const& member: structType->getMembers())
if (member.type->getCategory() != Category::Mapping && member.type->getCategory() != Category::Array)
{
retParamNames.push_back(member.first);
retParams.push_back(member.second);
retParamNames.push_back(member.name);
retParams.push_back(member.type);
}
}
else
@ -1109,7 +1128,7 @@ unsigned FunctionType::getSizeOnStack() const
return size;
}
TypePointer FunctionType::externalType() const
FunctionTypePointer FunctionType::externalFunctionType() const
{
TypePointers paramTypes;
TypePointers retParamTypes;
@ -1117,13 +1136,13 @@ TypePointer FunctionType::externalType() const
for (auto type: m_parameterTypes)
{
if (!type->externalType())
return TypePointer();
return FunctionTypePointer();
paramTypes.push_back(type->externalType());
}
for (auto type: m_returnParameterTypes)
{
if (!type->externalType())
return TypePointer();
return FunctionTypePointer();
retParamTypes.push_back(type->externalType());
}
return make_shared<FunctionType>(paramTypes, retParamTypes, m_location, m_arbitraryParameters);
@ -1141,12 +1160,12 @@ MemberList const& FunctionType::getMembers() const
case Location::Bare:
if (!m_members)
{
vector<pair<string, TypePointer>> members{
MemberList::MemberMap members{
{"value", make_shared<FunctionType>(parseElementaryTypeVector({"uint"}),
TypePointers{copyAndSetGasOrValue(false, true)},
Location::SetValue, false, m_gasSet, m_valueSet)}};
if (m_location != Location::Creation)
members.push_back(make_pair("gas", make_shared<FunctionType>(
members.push_back(MemberList::Member("gas", make_shared<FunctionType>(
parseElementaryTypeVector({"uint"}),
TypePointers{copyAndSetGasOrValue(true, false)},
Location::SetGas, false, m_gasSet, m_valueSet)));
@ -1158,6 +1177,37 @@ MemberList const& FunctionType::getMembers() const
}
}
bool FunctionType::canTakeArguments(TypePointers const& _argumentTypes) const
{
TypePointers const& parameterTypes = getParameterTypes();
if (takesArbitraryParameters())
return true;
else if (_argumentTypes.size() != parameterTypes.size())
return false;
else
return std::equal(
_argumentTypes.cbegin(),
_argumentTypes.cend(),
parameterTypes.cbegin(),
[](TypePointer const& argumentType, TypePointer const& parameterType)
{
return argumentType->isImplicitlyConvertibleTo(*parameterType);
}
);
}
bool FunctionType::hasEqualArgumentTypes(FunctionType const& _other) const
{
if (m_parameterTypes.size() != _other.m_parameterTypes.size())
return false;
return equal(
m_parameterTypes.cbegin(),
m_parameterTypes.cend(),
_other.m_parameterTypes.cbegin(),
[](TypePointer const& _a, TypePointer const& _b) -> bool { return *_a == *_b; }
);
}
string FunctionType::externalSignature(std::string const& _name) const
{
std::string funcName = _name;
@ -1168,7 +1218,7 @@ string FunctionType::externalSignature(std::string const& _name) const
}
string ret = funcName + "(";
TypePointers externalParameterTypes = dynamic_cast<FunctionType const&>(*externalType()).getParameterTypes();
TypePointers externalParameterTypes = externalFunctionType()->getParameterTypes();
for (auto it = externalParameterTypes.cbegin(); it != externalParameterTypes.cend(); ++it)
{
solAssert(!!(*it), "Parameter should have external type");
@ -1178,6 +1228,11 @@ string FunctionType::externalSignature(std::string const& _name) const
return ret + ")";
}
u256 FunctionType::externalIdentifier() const
{
return FixedHash<4>::Arith(FixedHash<4>(dev::sha3(externalSignature())));
}
TypePointers FunctionType::parseElementaryTypeVector(strings const& _types)
{
TypePointers pointers;
@ -1261,7 +1316,7 @@ MemberList const& TypeType::getMembers() const
// We need to lazy-initialize it because of recursive references.
if (!m_members)
{
vector<pair<string, TypePointer>> members;
MemberList::MemberMap members;
if (m_actualType->getCategory() == Category::Contract && m_currentContract != nullptr)
{
ContractDefinition const& contract = dynamic_cast<ContractType const&>(*m_actualType).getContractDefinition();
@ -1270,14 +1325,14 @@ MemberList const& TypeType::getMembers() const
// We are accessing the type of a base contract, so add all public and protected
// members. Note that this does not add inherited functions on purpose.
for (Declaration const* decl: contract.getInheritableMembers())
members.push_back(make_pair(decl->getName(), decl->getType()));
members.push_back(MemberList::Member(decl->getName(), decl->getType(), decl));
}
else if (m_actualType->getCategory() == Category::Enum)
{
EnumDefinition const& enumDef = dynamic_cast<EnumType const&>(*m_actualType).getEnumDefinition();
auto enumType = make_shared<EnumType>(enumDef);
for (ASTPointer<EnumValue> const& enumValue: enumDef.getMembers())
members.push_back(make_pair(enumValue->getName(), enumType));
members.push_back(MemberList::Member(enumValue->getName(), enumType));
}
m_members.reset(new MemberList(members));
}

70
libsolidity/Types.h

@ -69,17 +69,43 @@ private:
class MemberList
{
public:
using MemberMap = std::vector<std::pair<std::string, TypePointer>>;
struct Member
{
Member(std::string const& _name, TypePointer const& _type, Declaration const* _declaration = nullptr):
name(_name),
type(_type),
declaration(_declaration)
{
}
std::string name;
TypePointer type;
Declaration const* declaration = nullptr;
};
using MemberMap = std::vector<Member>;
MemberList() {}
explicit MemberList(MemberMap const& _members): m_memberTypes(_members) {}
MemberList& operator=(MemberList&& _other);
TypePointer getMemberType(std::string const& _name) const
{
TypePointer type;
for (auto const& it: m_memberTypes)
if (it.first == _name)
return it.second;
return TypePointer();
if (it.name == _name)
{
solAssert(!type, "Requested member type by non-unique name.");
type = it.type;
}
return type;
}
MemberMap membersByName(std::string const& _name) const
{
MemberMap members;
for (auto const& it: m_memberTypes)
if (it.name == _name)
members.push_back(it);
return members;
}
/// @returns the offset of the given member in storage slots and bytes inside a slot or
/// a nullptr if the member is not part of storage.
@ -404,12 +430,20 @@ public:
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual TypePointer unaryOperatorResult(Token::Value _operator) const override;
virtual bool operator==(Type const& _other) const override;
virtual unsigned getCalldataEncodedSize(bool _padded = true) const override
{
return externalType()->getCalldataEncodedSize(_padded);
}
virtual unsigned getStorageBytes() const override { return 20; }
virtual bool canLiveOutsideStorage() const override { return true; }
virtual bool isValueType() const override { return true; }
virtual std::string toString() const override;
virtual MemberList const& getMembers() const override;
virtual TypePointer externalType() const override { return std::make_shared<IntegerType>(160, IntegerType::Modifier::Address); }
virtual TypePointer externalType() const override
{
return std::make_shared<IntegerType>(160, IntegerType::Modifier::Address);
}
bool isSuper() const { return m_super; }
ContractDefinition const& getContractDefinition() const { return m_contract; }
@ -472,13 +506,21 @@ public:
explicit EnumType(EnumDefinition const& _enum): m_enum(_enum) {}
virtual TypePointer unaryOperatorResult(Token::Value _operator) const override;
virtual bool operator==(Type const& _other) const override;
virtual unsigned getCalldataEncodedSize(bool _padded = true) const override
{
return externalType()->getCalldataEncodedSize(_padded);
}
virtual unsigned getSizeOnStack() const override { return 1; }
virtual unsigned getStorageBytes() const override;
virtual bool canLiveOutsideStorage() const override { return true; }
virtual std::string toString() const override;
virtual bool isValueType() const override { return true; }
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual TypePointer externalType() const override { return std::make_shared<IntegerType>(8 * int(getStorageBytes())); }
virtual TypePointer externalType() const override
{
return std::make_shared<IntegerType>(8 * int(getStorageBytes()));
}
EnumDefinition const& getEnumDefinition() const { return m_enum; }
/// @returns the value that the string has in the Enum
@ -512,9 +554,12 @@ public:
virtual Category getCategory() const override { return Category::Function; }
/// @returns TypePointer of a new FunctionType object. All input/return parameters are an appropriate external types of input/return parameters of current function.
/// Returns an empty shared pointer if one of the input/return parameters does not have an externaltype.
virtual TypePointer externalType() const override;
/// @returns TypePointer of a new FunctionType object. All input/return parameters are an
/// appropriate external types of input/return parameters of current function.
/// Returns an empty shared pointer if one of the input/return parameters does not have an
/// external type.
virtual FunctionTypePointer externalFunctionType() const;
virtual TypePointer externalType() const override { return externalFunctionType(); }
explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true);
explicit FunctionType(VariableDeclaration const& _varDecl);
@ -554,11 +599,18 @@ public:
virtual unsigned getSizeOnStack() const override;
virtual MemberList const& getMembers() const override;
/// @returns true if this function can take the given argument types (possibly
/// after implicit conversion).
bool canTakeArguments(TypePointers const& _arguments) const;
bool hasEqualArgumentTypes(FunctionType const& _other) const;
Location const& getLocation() const { return m_location; }
/// @returns the external signature of this function type given the function name
/// If @a _name is not provided (empty string) then the @c m_declaration member of the
/// function type is used
std::string externalSignature(std::string const& _name = "") const;
/// @returns the external identifier of this function (the hash of the signature).
u256 externalIdentifier() const;
Declaration const& getDeclaration() const
{
solAssert(m_declaration, "Requested declaration from a FunctionType that has none");

8
libtestutils/Common.cpp

@ -20,6 +20,7 @@
*/
#include <random>
#include <boost/filesystem.hpp>
#include <libdevcore/CommonData.h>
#include <libdevcore/CommonIO.h>
#include <libdevcrypto/FileSystem.h>
@ -29,6 +30,8 @@ using namespace std;
using namespace dev;
using namespace dev::test;
const char* TestChannel::name() { return "TST"; }
std::string dev::test::getTestPath()
{
string testPath;
@ -71,6 +74,11 @@ std::string dev::test::toTestFilePath(std::string const& _filename)
return getTestPath() + "/" + _filename + ".json";
}
std::string dev::test::getFolder(std::string const& _file)
{
return boost::filesystem::path(_file).parent_path().string();
}
std::string dev::test::getRandomPath()
{
std::stringstream stream;

3
libtestutils/Common.h

@ -30,13 +30,14 @@ namespace dev
namespace test
{
struct TestChannel: public LogChannel { static const char* name() { return "TEST"; } };
struct TestChannel: public LogChannel { static const char* name(); };
#define ctest dev::LogOutputStream<dev::test::TestChannel, true>()
std::string getTestPath();
int randomNumber();
Json::Value loadJsonFromFile(std::string const& _path);
std::string toTestFilePath(std::string const& _filename);
std::string getFolder(std::string const& _file);
std::string getRandomPath();
}

4
mix/CodeModel.cpp

@ -398,8 +398,8 @@ SolidityType CodeModel::nodeType(dev::solidity::Type const* _type)
StructType const* s = dynamic_cast<StructType const*>(_type);
for(auto const& structMember: s->getMembers())
{
auto slotAndOffset = s->getStorageOffsetsOfMember(structMember.first);
r.members.push_back(SolidityDeclaration { QString::fromStdString(structMember.first), nodeType(structMember.second.get()), slotAndOffset.first, slotAndOffset.second });
auto slotAndOffset = s->getStorageOffsetsOfMember(structMember.name);
r.members.push_back(SolidityDeclaration { QString::fromStdString(structMember.name), nodeType(structMember.type.get()), slotAndOffset.first, slotAndOffset.second });
}
}
break;

2
mix/MixClient.cpp

@ -250,7 +250,7 @@ void MixClient::mine()
{
WriteGuard l(x_state);
m_state.commitToMine(bc());
m_state.completeMine();
m_state.completeMine<Ethash>(Ethash::Solution());
bc().import(m_state.blockData(), m_stateDB, ImportRequirements::Default & ~ImportRequirements::ValidNonce);
/*
GenericFarm<ProofOfWork> f;

29
mix/qml/CodeEditorView.qml

@ -3,6 +3,7 @@ import QtQuick.Window 2.0
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0
import QtQuick.Dialogs 1.1
import Qt.labs.settings 1.0
Item {
id: codeEditorView
@ -74,6 +75,7 @@ Item {
}
editor.document = document;
editor.sourceName = document.documentId;
editor.setFontSize(editorSettings.fontSize);
editor.setText(data, document.syntaxMode);
editor.changeGeneration();
}
@ -158,6 +160,14 @@ Item {
}
}
function setFontSize(size) {
if (size <= 10 || size >= 48)
return;
editorSettings.fontSize = size;
for (var i = 0; i < editors.count; i++)
editors.itemAt(i).item.setFontSize(size);
}
Component.onCompleted: projectModel.codeEditor = codeEditorView;
Connections {
@ -317,4 +327,23 @@ Item {
ListModel {
id: editorListModel
}
Action {
id: increaseFontSize
text: qsTr("Increase Font Size")
shortcut: "Ctrl+="
onTriggered: setFontSize(editorSettings.fontSize + 1)
}
Action {
id: decreaseFontSize
text: qsTr("Decrease Font Size")
shortcut: "Ctrl+-"
onTriggered: setFontSize(editorSettings.fontSize - 1)
}
Settings {
id: editorSettings
property int fontSize: 12;
}
}

8
mix/qml/WebCodeEditor.qml

@ -19,6 +19,7 @@ Item {
property var currentBreakpoints: []
property string sourceName
property var document
property int fontSize: 0
function setText(text, mode) {
currentText = text;
@ -76,6 +77,12 @@ Item {
editorBrowser.runJavaScript("goToCompilationError()", function(result) {});
}
function setFontSize(size) {
fontSize = size;
if (initialized && editorBrowser)
editorBrowser.runJavaScript("setFontSize(" + size + ")", function(result) {});
}
Clipboard
{
id: clipboard
@ -108,6 +115,7 @@ Item {
{
if (!loading && editorBrowser) {
initialized = true;
setFontSize(fontSize);
setText(currentText, currentMode);
runJavaScript("getTextChanged()", function(result) { });
pollTimer.running = true;

2
mix/qml/WebPreview.qml

@ -186,7 +186,7 @@ Item {
if (documentName === urlInput.text.replace(httpServer.url + "/", "")) {
//root page, inject deployment script
content = "<script>web3=parent.web3;contracts=parent.contracts;</script>\n" + content;
content = "<script>web3=parent.web3;BigNumber=parent.BigNumber;contracts=parent.contracts;</script>\n" + content;
_request.setResponseContentType("text/html");
}
_request.setResponse(content);

1
mix/qml/html/WebContainer.html

@ -21,6 +21,7 @@ updateContracts = function(contracts) {
if (window.web3) {
window.web3.reset();
window.contracts = {};
window.BigNumber = require('bignumber.js');
for (var c in contracts) {
var contractProto = window.web3.eth.contract(contracts[c].interface);
var contract = new contractProto(contracts[c].address);

65
mix/qml/html/cm/inkpot.css

@ -0,0 +1,65 @@
/*
Inkpot theme for code-mirror
https://github.com/ciaranm/inkpot
*/
/* Color scheme for code-mirror */
.cm-s-inkpot.CodeMirror {
color: #cfbfad;
text-shadow: #1e1e27 0 1px;
background-color: #1e1e27;
line-height: 1.45em;
color-profile: sRGB;
rendering-intent: auto;
}
.cm-s-inkpot .CodeMirror-gutters { background: #2e2e2e; border-right: 0px solid #aaa; }
.cm-s-inkpot .CodeMirror-linenumber { color: #8b8bcd; }
.cm-s-inkpot .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-inkpot span.cm-comment { color: #cd8b00; }
.cm-s-inkpot span.cm-def { color: #cfbfad; font-weight:bold; }
.cm-s-inkpot span.cm-keyword { color: #808bed; }
.cm-s-inkpot span.cm-builtin { color: #cfbfad; }
.cm-s-inkpot span.cm-variable { color: #cfbfad; }
.cm-s-inkpot span.cm-string { color: #ffcd8b; }
.cm-s-inkpot span.cm-number { color: #f0ad6d; }
.cm-s-inkpot span.cm-atom { color: #cb6ecb; }
.cm-s-inkpot span.cm-variable-2 { color: #ffb8ff; }
.cm-s-inkpot span.cm-meta { color: #409090; }
.cm-s-inkpot span.cm-qualifier { color: #808bed; }
.cm-s-inkpot span.cm-tag { color: #808bed; }
.cm-s-inkpot span.cm-attribute { color: #FF5555; }
.cm-s-inkpot span.cm-error { color: #f00; }
.cm-s-inkpot .cm-bracket { color: #cb4b16; }
.cm-s-inkpot .CodeMirror-matchingbracket { color: #859900; }
.cm-s-inkpot .CodeMirror-nonmatchingbracket { color: #dc322f; }
.cm-s-inkpot .CodeMirror-selected { background: #4e4e8f !important; }
span.CodeMirror-selectedtext { color: #ffffff !important; }
/* Code execution */
.CodeMirror-exechighlight {
border-bottom: double 1px #94A2A2;
}
/* Error annotation */
.CodeMirror-errorannotation {
border-bottom: 1px solid #DD3330;
margin-bottom: 4px;
}
.CodeMirror-errorannotation-context {
font-family: monospace;
color: #EEE9D5;
background: #b58900;
padding: 2px;
text-shadow: none !important;
border-top: solid 2px #063742;
}

3
mix/qml/html/codeeditor.html

@ -1,7 +1,8 @@
<!doctype html>
<meta charset="utf-8"/>
<link rel="stylesheet" href="cm/codemirror.css">
<link rel="stylesheet" href="cm/solarized.css">
<!--link rel="stylesheet" href="cm/solarized.css"-->
<link rel="stylesheet" href="cm/inkpot.css">
<link rel="stylesheet" href="cm/fullscreen.css">
<link rel="stylesheet" href="cm/dialog.css">
<link rel="stylesheet" href="cm/show-hint.css">

9
mix/qml/html/codeeditor.js

@ -9,7 +9,7 @@ var editor = CodeMirror(document.body, {
});
var ternServer;
editor.setOption("theme", "solarized dark");
editor.setOption("theme", "inkpot");
editor.setOption("indentUnit", 4);
editor.setOption("indentWithTabs", true);
editor.setOption("fullScreen", true);
@ -194,4 +194,11 @@ goToCompilationError = function()
editor.setCursor(annotation.line, annotation.column)
}
setFontSize = function(size)
{
editor.getWrapperElement().style["font-size"] = size + "px";
editor.refresh();
}
editor.setOption("extraKeys", extraKeys);

1
mix/web.qrc

@ -32,6 +32,7 @@
<file>qml/html/cm/show-hint.js</file>
<file>qml/html/cm/signal.js</file>
<file>qml/html/cm/solarized.css</file>
<file>qml/html/cm/inkpot.css</file>
<file>qml/html/cm/solidity.js</file>
<file>qml/html/cm/solidityToken.js</file>
<file>qml/html/cm/tern.js</file>

2
neth/main.cpp

@ -542,7 +542,7 @@ int main(int argc, char** argv)
VMFactory::setKind(jit ? VMKind::JIT : VMKind::Interpreter);
auto netPrefs = publicIP.empty() ? NetworkPreferences(listenIP ,listenPort, upnp) : NetworkPreferences(publicIP, listenIP ,listenPort, upnp);
auto nodesState = contents((dbPath.size() ? dbPath : getDataDir()) + "/network.rlp");
std::string clientImplString = "NEthereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) + (jit ? "/JIT" : "");
std::string clientImplString = "N++eth/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) + (jit ? "/JIT" : "");
dev::WebThreeDirect web3(
clientImplString,
dbPath,

60
test/CMakeLists.txt

@ -1,14 +1,39 @@
cmake_policy(SET CMP0015 NEW)
aux_source_directory(. SRC_LIST)
list(REMOVE_ITEM SRC_LIST "./createRandomVMTest.cpp")
list(REMOVE_ITEM SRC_LIST "./createRandomStateTest.cpp")
list(REMOVE_ITEM SRC_LIST "./checkRandomVMTest.cpp")
list(REMOVE_ITEM SRC_LIST "./checkRandomStateTest.cpp")
if (NOT JSONRPC)
list(REMOVE_ITEM SRC_LIST "./AccountHolder.cpp")
endif()
macro (add_sources)
file (RELATIVE_PATH _relPath "${CMAKE_SOURCE_DIR}/test" "${CMAKE_CURRENT_SOURCE_DIR}")
foreach (_src ${ARGN})
if (_relPath)
list (APPEND SRC "${_relPath}/${_src}")
else()
list (APPEND SRC "${_src}")
endif()
endforeach()
if (_relPath)
# propagate SRCS to parent directory
set (SRC ${SRC} PARENT_SCOPE)
endif()
endmacro()
add_subdirectory(fuzzTesting)
add_subdirectory(libdevcore)
add_subdirectory(libdevcrypto)
add_subdirectory(libethcore)
add_subdirectory(libethereum)
add_subdirectory(libevm)
add_subdirectory(libnatspec)
add_subdirectory(libp2p)
if (SOLIDITY)
add_subdirectory(libsolidity)
endif ()
if (JSONRPC)
add_subdirectory(libweb3jsonrpc)
endif ()
add_subdirectory(libwhisper)
set(SRC_LIST ${SRC_LIST} ${SRC})
include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(BEFORE ..)
@ -34,10 +59,6 @@ endforeach(file)
file(GLOB HEADERS "*.h")
add_executable(testeth ${SRC_LIST} ${HEADERS})
add_executable(createRandomVMTest createRandomVMTest.cpp vm.cpp TestHelper.cpp Stats.cpp)
add_executable(createRandomStateTest createRandomStateTest.cpp TestHelper.cpp Stats.cpp)
add_executable(checkRandomVMTest checkRandomVMTest.cpp vm.cpp TestHelper.cpp Stats.cpp)
add_executable(checkRandomStateTest checkRandomStateTest.cpp TestHelper.cpp Stats.cpp)
target_link_libraries(testeth ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
target_link_libraries(testeth ${CURL_LIBRARIES})
@ -57,23 +78,6 @@ if (JSONRPC)
target_link_libraries(testeth ${JSON_RPC_CPP_CLIENT_LIBRARIES})
endif()
target_link_libraries(createRandomVMTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
target_link_libraries(createRandomVMTest ethereum)
target_link_libraries(createRandomVMTest ethcore)
target_link_libraries(createRandomVMTest testutils)
target_link_libraries(createRandomStateTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
target_link_libraries(createRandomStateTest ethereum)
target_link_libraries(createRandomStateTest ethcore)
target_link_libraries(createRandomStateTest testutils)
target_link_libraries(checkRandomVMTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
target_link_libraries(checkRandomVMTest ethereum)
target_link_libraries(checkRandomVMTest ethcore)
target_link_libraries(checkRandomVMTest testutils)
target_link_libraries(checkRandomStateTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
target_link_libraries(checkRandomStateTest ethereum)
target_link_libraries(checkRandomStateTest ethcore)
target_link_libraries(checkRandomStateTest testutils)
enable_testing()
set(CTEST_OUTPUT_ON_FAILURE TRUE)

120
test/JSON_test.sol

@ -0,0 +1,120 @@
contract JSON_Test {
event Log0(uint value) ;
event Log0Anonym (uint value) anonymous;
event Log1(bool indexed aBool, uint value);
event Log1Anonym(bool indexed aBool, uint value) anonymous;
event Log2(bool indexed aBool, address indexed aAddress, uint value);
event Log2Anonym(bool indexed aBool, address indexed aAddress, uint value) anonymous;
event Log3(bool indexed aBool, address indexed aAddress, bytes32 indexed aBytes32, uint value);
event Log3Anonym(bool indexed aBool, address indexed aAddress, bytes32 indexed aBytes32, uint value) anonymous;
event Log4(bool indexed aBool, address indexed aAddress, bytes32 indexed aBytes32, int8 aInt8, uint value);
event Log4Anonym(bool indexed aBool, address indexed aAddress, bytes32 indexed aBytes32, int8 aInt8, uint value) anonymous;
function JSON_Test() {
}
function setBool(bool _bool) {
myBool = _bool;
}
function setInt8(int8 _int8) {
myInt8 = _int8;
}
function setUint8(uint8 _uint8) {
myUint8 = _uint8;
}
function setInt256(int256 _int256) {
myInt256 = _int256;
}
function setUint256(uint256 _uint256) {
myUint256 = _uint256;
}
function setAddress(address _address) {
myAddress = _address;
}
function setBytes32(bytes32 _bytes32) {
myBytes32 = _bytes32;
}
function getBool() returns (bool ret) {
return myBool;
}
function getInt8() returns (int8 ret) {
return myInt8;
}
function getUint8() returns (uint8 ret) {
return myUint8;
}
function getInt256() returns (int256 ret) {
return myInt256;
}
function getUint256() returns (uint256 ret) {
return myUint256;
}
function getAddress() returns (address ret) {
return myAddress;
}
function getBytes32() returns (bytes32 ret) {
return myBytes32;
}
function fireEventLog0() {
Log0(42);
}
function fireEventLog0Anonym() {
Log0Anonym(42);
}
function fireEventLog1() {
Log1(true, 42);
}
function fireEventLog1Anonym() {
Log1Anonym(true, 42);
}
function fireEventLog2() {
Log2(true, msg.sender, 42);
}
function fireEventLog2Anonym() {
Log2Anonym(true, msg.sender, 42);
}
function fireEventLog3() {
Log3(true, msg.sender, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 42);
}
function fireEventLog3Anonym() {
Log3Anonym(true, msg.sender, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, 42);
}
function fireEventLog4() {
Log4(true, msg.sender, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, -23, 42);
}
function fireEventLog4Anonym() {
Log4Anonym(true, msg.sender, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, -23, 42);
}
bool myBool;
int8 myInt8;
uint8 myUint8;
int256 myInt256;
uint256 myUint256;
address myAddress;
bytes32 myBytes32;
}

12
test/TestHelper.cpp

@ -23,9 +23,6 @@
#include <thread>
#include <chrono>
#include <boost/filesystem/path.hpp>
#include <libethereum/Client.h>
#include <liblll/Compiler.h>
#include <libevm/VMFactory.h>
@ -542,6 +539,8 @@ void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _e
void userDefinedTest(string testTypeFlag, std::function<void(json_spirit::mValue&, bool)> doTests)
{
Options::get(); // parse command line options, e.g. to enable JIT
for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i)
{
string arg = boost::unit_test::framework::master_test_suite().argv[i];
@ -592,7 +591,7 @@ void userDefinedTest(string testTypeFlag, std::function<void(json_spirit::mValue
}
}
void executeTests(const string& _name, const string& _testPathAppendix, std::function<void(json_spirit::mValue&, bool)> doTests)
void executeTests(const string& _name, const string& _testPathAppendix, const boost::filesystem::path _pathToFiller, std::function<void(json_spirit::mValue&, bool)> doTests)
{
string testPath = getTestPath();
testPath += _testPathAppendix;
@ -607,9 +606,8 @@ void executeTests(const string& _name, const string& _testPathAppendix, std::fun
cnote << "Populating tests...";
json_spirit::mValue v;
boost::filesystem::path p(__FILE__);
boost::filesystem::path dir = p.parent_path();
string s = asString(dev::contents(dir.string() + "/" + _name + "Filler.json"));
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + dir.string() + "/" + _name + "Filler.json is empty.");
string s = asString(dev::contents(_pathToFiller.string() + "/" + _name + "Filler.json"));
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _pathToFiller.string() + "/" + _name + "Filler.json is empty.");
json_spirit::read_string(s, v);
doTests(v, true);
writeFile(testPath + "/" + _name + ".json", asBytes(json_spirit::write_string(v, true)));

3
test/TestHelper.h

@ -24,6 +24,7 @@
#include <functional>
#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>
#include "JsonSpiritHeaders.h"
#include <libethereum/State.h>
@ -155,7 +156,7 @@ void checkStorage(std::map<u256, u256> _expectedStore, std::map<u256, u256> _res
void checkLog(eth::LogEntries _resultLogs, eth::LogEntries _expectedLogs);
void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _expectedCallCreates);
void executeTests(const std::string& _name, const std::string& _testPathAppendix, std::function<void(json_spirit::mValue&, bool)> doTests);
void executeTests(const std::string& _name, const std::string& _testPathAppendix, const boost::filesystem::path _pathToFiller, std::function<void(json_spirit::mValue&, bool)> doTests);
void userDefinedTest(std::string testTypeFlag, std::function<void(json_spirit::mValue&, bool)> doTests);
RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject& _tObj);
eth::LastHashes lastHashes(u256 _currentBlockNumber);

247
test/bcJS_API_TestFiller.json

@ -1,247 +0,0 @@
{
"JS_API_Tests" : {
"genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "131072",
"extraData" : "0x42",
"gasLimit" : "3141592",
"gasUsed" : "0",
"number" : "0",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a",
"timestamp" : "0x54c98c81",
"mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"nonce" : "0x0102030405060708",
"transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"expect" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "70"
},
"6295ee1b4f6dd65047762f924ecd367c17eabf8f" : {
"storage" : {
"0x" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"0x01" : "0x42",
"0x02" : "0x23",
"0x03" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"0x04" : "0x01",
"0x05" : "0x55114a49"
}
}
},
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "10000000000000",
"nonce" : "0",
"code" : "",
"storage": {}
},
"6295ee1b4f6dd65047762f924ecd367c17eabf8f" : {
"balance" : "100000",
"code" : "0x60003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b5056",
"nonce" : "0",
"storage" : {
"0x" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"0x01" : "0x42",
"0x02" : "0x23",
"0x03" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"0x05" : "0x54c98c81"
}
}
},
"blocks" : [
{
"transactions" : [
{
"data" : "0x60406103ca600439600451602451336000819055506000600481905550816001819055508060028190555042600581905550336003819055505050610381806100496000396000f30060003560e060020a9004806343d726d61461004257806391b7f5ed14610050578063d686f9ee14610061578063f5bade661461006f578063fcfff16f1461008057005b61004a6101de565b60006000f35b61005b6004356100bf565b60006000f35b610069610304565b60006000f35b61007a60043561008e565b60006000f35b6100886100f0565b60006000f35b600054600160a060020a031633600160a060020a031614156100af576100b4565b6100bc565b806001819055505b50565b600054600160a060020a031633600160a060020a031614156100e0576100e5565b6100ed565b806002819055505b50565b600054600160a060020a031633600160a060020a031614806101255750600354600160a060020a031633600160a060020a0316145b61012e57610161565b60016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a16101dc565b60045460011480610173575060015434105b6101b85760016004819055507f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a560006000a142600581905550336003819055506101db565b33600160a060020a03166000346000600060006000848787f16101d757005b5050505b5b565b60006004546000146101ef576101f4565b610301565b600054600160a060020a031633600160a060020a031614801561022c5750600054600160a060020a0316600354600160a060020a0316145b61023557610242565b6000600481905550610301565b600354600160a060020a031633600160a060020a03161461026257610300565b600554420360025402905060015481116102c757600354600160a060020a0316600082600154036000600060006000848787f161029b57005b505050600054600160a060020a03166000826000600060006000848787f16102bf57005b5050506102ee565b600054600160a060020a031660006001546000600060006000848787f16102ea57005b5050505b60006004819055506000546003819055505b5b50565b6000600054600160a060020a031633600160a060020a031614156103275761032c565b61037e565b600554420360025402905060015481116103455761037d565b600054600160a060020a031660006001546000600060006000848787f161036857005b50505060006004819055506000546003819055505b5b505600000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000023",
"gasLimit" : "600000",
"gasPrice" : "1",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "",
"value" : "100000"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "1",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "0xfcfff16f",
"gasLimit" : "600000",
"gasPrice" : "1",
"nonce" : "2",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "0x42"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "3",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
{
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"difficulty" : "131072",
"extraData" : "0x",
"gasLimit" : "3141592",
"gasUsed" : "0",
"hash" : "9de9879b6a81d1b6c4993c63c90a3c9d1e775f14572694778e828bc64972ae04",
"mixHash" : "b557f905d29ed0fca99d65d0adcce698dee97cf72a13c7cd8d7a7826b8eee770",
"nonce" : "18a524c1790fa83b",
"number" : "2",
"parentHash" : "6134fc6b5d99ee03c4aab1592640f6f9dcbc850668d75d631aee34989b938fae",
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "ff640b30d613c35dad43e3693329e1b1ee6350f989cf46a288025a1cbfdab9cd",
"timestamp" : "0x54c98c82",
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
{
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "bcde5374fce5edbc8e2a8697c15331677e6ebf0b",
"difficulty" : "131072",
"extraData" : "0x",
"gasLimit" : "3141592",
"gasUsed" : "0",
"hash" : "9de9879b6a81d1b6c4993c63c90a3c9d1e775f14572694778e828bc64972ae04",
"mixHash" : "b557f905d29ed0fca99d65d0adcce698dee97cf72a13c7cd8d7a7826b8eee770",
"nonce" : "18a524c1790fa83b",
"number" : "2",
"parentHash" : "6134fc6b5d99ee03c4aab1592640f6f9dcbc850668d75d631aee34989b938fae",
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "ff640b30d613c35dad43e3693329e1b1ee6350f989cf46a288025a1cbfdab9cd",
"timestamp" : "0x54c98c82",
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
}
]
},
{
"transactions" : [
{
"data" : "",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "4",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "5",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
{
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "bcde5374fce5edbc8e2a8697c15331677e6ebf0b",
"difficulty" : "131072",
"extraData" : "0x",
"gasLimit" : "314159",
"gasUsed" : "0",
"hash" : "9de9879b6a81d1b6c4993c63c90a3c9d1e775f14572694778e828bc64972ae04",
"mixHash" : "b557f905d29ed0fca99d65d0adcce698dee97cf72a13c7cd8d7a7826b8eee770",
"nonce" : "18a524c1790fa83b",
"number" : "2",
"parentHash" : "6134fc6b5d99ee03c4aab1592640f6f9dcbc850668d75d631aee34989b938fae",
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "ff640b30d613c35dad43e3693329e1b1ee6350f989cf46a288025a1cbfdab9cd",
"timestamp" : "0x54c98c82",
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
}
]
},
{
"transactions" : [
{
"data" : "",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "6",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "7",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "8",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : "10"
}
],
"uncleHeaders" : [
]
}
]
}
}

579
test/bcRPC_API_TestFiller.json

@ -0,0 +1,579 @@
{
"RPC_API_Test" : {
"genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "131072",
"extraData" : "0x42",
"gasLimit" : "3141592",
"gasUsed" : "0",
"number" : "0",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a",
"timestamp" : "0x54c98c81",
"mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"nonce" : "0x0102030405060708",
"transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "10000000000000",
"nonce" : "0",
"code" : "",
"storage": {}
}
},
"blocks" : [
{
"transactions" : [
{
"data" : "create contract: 6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"data" : "0x5b5b610705806100106000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063102accc11461012c57806312a7b9141461013a5780631774e6461461014c5780631e26fd331461015d5780631f9030371461016e578063343a875d1461018057806338cc4831146101955780634e7ad367146101bd57806357cb2fc4146101cb57806365538c73146101e057806368895979146101ee57806376bc21d9146102005780639a19a9531461020e5780639dc2c8f51461021f578063a53b1c1e1461022d578063a67808571461023e578063b61c05031461024c578063c2b12a731461025a578063d2282dc51461026b578063e30081a01461027c578063e8beef5b1461028d578063f38b06001461029b578063f5b53e17146102a9578063fd408767146102bb57005b6101346104d6565b60006000f35b61014261039b565b8060005260206000f35b610157600435610326565b60006000f35b6101686004356102c9565b60006000f35b610176610442565b8060005260206000f35b6101886103d3565b8060ff1660005260206000f35b61019d610413565b8073ffffffffffffffffffffffffffffffffffffffff1660005260206000f35b6101c56104c5565b60006000f35b6101d36103b7565b8060000b60005260206000f35b6101e8610454565b60006000f35b6101f6610401565b8060005260206000f35b61020861051f565b60006000f35b6102196004356102e5565b60006000f35b610227610693565b60006000f35b610238600435610342565b60006000f35b610246610484565b60006000f35b610254610493565b60006000f35b61026560043561038d565b60006000f35b610276600435610350565b60006000f35b61028760043561035e565b60006000f35b6102956105b4565b60006000f35b6102a3610547565b60006000f35b6102b16103ef565b8060005260206000f35b6102c3610600565b60006000f35b80600060006101000a81548160ff021916908302179055505b50565b80600060016101000a81548160ff02191690837f01000000000000000000000000000000000000000000000000000000000000009081020402179055505b50565b80600060026101000a81548160ff021916908302179055505b50565b806001600050819055505b50565b806002600050819055505b50565b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b50565b806004600050819055505b50565b6000600060009054906101000a900460ff1690506103b4565b90565b6000600060019054906101000a900460000b90506103d0565b90565b6000600060029054906101000a900460ff1690506103ec565b90565b600060016000505490506103fe565b90565b60006002600050549050610410565b90565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905061043f565b90565b60006004600050549050610451565b90565b7f65c9ac8011e286e89d02a269890f41d67ca2cc597b2c76c7c69321ff492be5806000602a81526020016000a15b565b6000602a81526020016000a05b565b60017f81933b308056e7e85668661dcd102b1f22795b4431f9cf4625794f381c271c6b6000602a81526020016000a25b565b60016000602a81526020016000a15b565b3373ffffffffffffffffffffffffffffffffffffffff1660017f0e216b62efbb97e751a2ce09f607048751720397ecfb9eef1e48a6644948985b6000602a81526020016000a35b565b3373ffffffffffffffffffffffffffffffffffffffff1660016000602a81526020016000a25b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001023373ffffffffffffffffffffffffffffffffffffffff1660017f317b31292193c2a4f561cc40a95ea0d97a2733f14af6d6d59522473e1f3ae65f6000602a81526020016000a45b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001023373ffffffffffffffffffffffffffffffffffffffff1660016000602a81526020016000a35b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001023373ffffffffffffffffffffffffffffffffffffffff1660017fd5f0a30e4be0c6be577a71eceb7464245a796a7e6a55c0d971837b250de05f4e60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe98152602001602a81526020016000a45b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001023373ffffffffffffffffffffffffffffffffffffffff16600160007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe98152602001602a81526020016000a35b56",
"gasLimit" : "3141592",
"gasPrice" : "1",
"nonce" : "0",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "getBool",
"data" : "0x12a7b914",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "1",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "getInt8",
"data" : "0x57cb2fc4",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "2",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "getUint8",
"data" : "0x343a875d",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "3",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
{
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"difficulty" : "131072",
"extraData" : "0x",
"gasLimit" : "3141592",
"gasUsed" : "0",
"hash" : "9de9879b6a81d1b6c4993c63c90a3c9d1e775f14572694778e828bc64972ae04",
"mixHash" : "b557f905d29ed0fca99d65d0adcce698dee97cf72a13c7cd8d7a7826b8eee770",
"nonce" : "18a524c1790fa83b",
"number" : "2",
"parentHash" : "6134fc6b5d99ee03c4aab1592640f6f9dcbc850668d75d631aee34989b938fae",
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "ff640b30d613c35dad43e3693329e1b1ee6350f989cf46a288025a1cbfdab9cd",
"timestamp" : "0x54c98c82",
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
{
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "bcde5374fce5edbc8e2a8697c15331677e6ebf0b",
"difficulty" : "131072",
"extraData" : "0x",
"gasLimit" : "3141592",
"gasUsed" : "0",
"hash" : "9de9879b6a81d1b6c4993c63c90a3c9d1e775f14572694778e828bc64972ae04",
"mixHash" : "b557f905d29ed0fca99d65d0adcce698dee97cf72a13c7cd8d7a7826b8eee770",
"nonce" : "18a524c1790fa83b",
"number" : "2",
"parentHash" : "6134fc6b5d99ee03c4aab1592640f6f9dcbc850668d75d631aee34989b938fae",
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "ff640b30d613c35dad43e3693329e1b1ee6350f989cf46a288025a1cbfdab9cd",
"timestamp" : "0x54c98c82",
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
}
]
},
{
"transactions" : [
{
"data" : "getInt256",
"data" : "0xf5b53e17",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "4",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "getUint256",
"data" : "0x68895979",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "5",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "getAddress",
"data" : "0x38cc4831",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "6",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "getBytes32",
"data" : "0x1f903037",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "7",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "setBool",
"data" : "0x1e26fd330000000000000000000000000000000000000000000000000000000000000001",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "8",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "setBool",
"data" : "0x1e26fd330000000000000000000000000000000000000000000000000000000000000001",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "9",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "setInt8",
"data" : "0x9a19a953fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "10",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "setUint8",
"data" : "0x1774e6460000000000000000000000000000000000000000000000000000000000000008",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "11",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "setInt256",
"data" : "0xa53b1c1effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "12",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "setUint256",
"data" : "0xd2282dc5ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "13",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "setAddress",
"data" : "0xe30081a0aabbccffffffffffffffffffffffffffffffffffffffffffffffffffffffffee",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "14",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "setBytes32",
"data" : "0xc2b12a73aabbccffffffffffffffffffffffffffffffffffffffffffffffffffffffffee",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "15",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "getInt8",
"data" : "0x57cb2fc4",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "16",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "getUint8",
"data" : "0x343a875d",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "17",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "getInt256",
"data" : "0xf5b53e17",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "18",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "getUint256",
"data" : "0x68895979",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "19",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "getAddress",
"data" : "0x38cc4831",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "20",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "getBytes32",
"data" : "0x1f903037",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "21",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "log0",
"data" : "0x65538c73",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "22",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "log0a",
"data" : "0xa6780857",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "23",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "log1",
"data" : "0xb61c0503",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "24",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "log1a",
"data" : "0x4e7ad367",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "25",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "log2",
"data" : "0x102accc1",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "26",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "log2a",
"data" : "0x76bc21d9",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "27",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "log3",
"data" : "0xf38b0600",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "28",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "log3a",
"data" : "0xe8beef5b",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "29",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "log4",
"data" : "0xfd408767",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "30",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
},
{
"transactions" : [
{
"data" : "log4a",
"data" : "0x9dc2c8f5",
"gasLimit" : "314159",
"gasPrice" : "1",
"nonce" : "31",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "6295ee1b4f6dd65047762f924ecd367c17eabf8f",
"value" : "10"
}
],
"uncleHeaders" : [
]
}
]
}
}

0
test/fork.cpp → test/deprecated/fork.cpp

0
test/kademlia.cpp → test/deprecated/kademlia.cpp

0
test/main.cpp → test/deprecated/main.cpp

0
test/txTest.cpp → test/deprecated/txTest.cpp

31
test/fuzzTesting/CMakeLists.txt

@ -0,0 +1,31 @@
cmake_policy(SET CMP0015 NEW)
file(GLOB HEADERS "*.h")
include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(BEFORE ..)
include_directories(BEFORE ../..)
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${CRYPTOPP_INCLUDE_DIRS})
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
add_executable(createRandomVMTest "./createRandomVMTest.cpp" "../libevm/vm.cpp" "../TestHelper.cpp" "../Stats.cpp")
add_executable(createRandomStateTest "./createRandomStateTest.cpp" "../TestHelper.cpp" "../Stats.cpp")
add_executable(checkRandomVMTest "./checkRandomVMTest.cpp" "../libevm/vm.cpp" "../TestHelper.cpp" "../Stats.cpp")
add_executable(checkRandomStateTest "./checkRandomStateTest.cpp" "../TestHelper.cpp" "../Stats.cpp")
target_link_libraries(createRandomVMTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
target_link_libraries(createRandomVMTest ethereum)
target_link_libraries(createRandomVMTest ethcore)
target_link_libraries(createRandomVMTest testutils)
target_link_libraries(createRandomStateTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
target_link_libraries(createRandomStateTest ethereum)
target_link_libraries(createRandomStateTest ethcore)
target_link_libraries(createRandomStateTest testutils)
target_link_libraries(checkRandomVMTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
target_link_libraries(checkRandomVMTest ethereum)
target_link_libraries(checkRandomVMTest ethcore)
target_link_libraries(checkRandomVMTest testutils)
target_link_libraries(checkRandomStateTest ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
target_link_libraries(checkRandomStateTest ethereum)
target_link_libraries(checkRandomStateTest ethcore)
target_link_libraries(checkRandomStateTest testutils)

2
test/checkRandomStateTest.cpp → test/fuzzTesting/checkRandomStateTest.cpp

@ -26,7 +26,7 @@
#include <libdevcore/Log.h>
#include <libevm/VMFactory.h>
#include "TestHelper.h"
#include "vm.h"
#include "../libevm/vm.h"
#pragma GCC diagnostic ignored "-Wunused-parameter"
using namespace std;

3
test/checkRandomVMTest.cpp → test/fuzzTesting/checkRandomVMTest.cpp

@ -25,7 +25,8 @@
#include <libdevcore/Exceptions.h>
#include <libdevcore/Log.h>
#include <libevm/VMFactory.h>
#include "vm.h"
#include "../libevm/vm.h"
#pragma GCC diagnostic ignored "-Wunused-parameter"
using namespace std;

4
test/createRandomStateTest.cpp → test/fuzzTesting/createRandomStateTest.cpp

@ -35,8 +35,8 @@
#include <libdevcore/CommonData.h>
#include <libevmcore/Instruction.h>
#include <libevm/VMFactory.h>
#include "TestHelper.h"
#include "vm.h"
#include "../TestHelper.h"
#include "../libevm/vm.h"
using namespace std;
using namespace json_spirit;

2
test/createRandomVMTest.cpp → test/fuzzTesting/createRandomVMTest.cpp

@ -35,7 +35,7 @@
#include <libdevcore/CommonData.h>
#include <libevmcore/Instruction.h>
#include <libevm/VMFactory.h>
#include "vm.h"
#include "../libevm/vm.h"
using namespace std;
using namespace json_spirit;

5
test/libdevcore/CMakeLists.txt

@ -0,0 +1,5 @@
cmake_policy(SET CMP0015 NEW)
aux_source_directory(. SRCS)
add_sources(${SRCS})

4
test/rlp.cpp → test/libdevcore/rlp.cpp

@ -30,8 +30,8 @@
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
#include <algorithm>
#include "JsonSpiritHeaders.h"
#include "TestHelper.h"
#include "../JsonSpiritHeaders.h"
#include "../TestHelper.h"
using namespace std;
using namespace dev;

5
test/libdevcrypto/CMakeLists.txt

@ -0,0 +1,5 @@
cmake_policy(SET CMP0015 NEW)
aux_source_directory(. SRCS)
add_sources(${SRCS})

0
test/MemTrie.cpp → test/libdevcrypto/MemTrie.cpp

0
test/MemTrie.h → test/libdevcrypto/MemTrie.h

0
test/TrieHash.cpp → test/libdevcrypto/TrieHash.cpp

0
test/TrieHash.h → test/libdevcrypto/TrieHash.h

0
test/crypto.cpp → test/libdevcrypto/crypto.cpp

4
test/hexPrefix.cpp → test/libdevcrypto/hexPrefix.cpp

@ -24,11 +24,11 @@
#include <boost/test/unit_test.hpp>
#include "JsonSpiritHeaders.h"
#include "../JsonSpiritHeaders.h"
#include <libdevcore/Log.h>
#include <libdevcore/CommonIO.h>
#include <libdevcrypto/TrieCommon.h>
#include "TestHelper.h"
#include "../TestHelper.h"
using namespace std;
using namespace dev;

4
test/trie.cpp → test/libdevcrypto/trie.cpp

@ -25,12 +25,12 @@
#include <boost/test/unit_test.hpp>
#include "JsonSpiritHeaders.h"
#include "../JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libdevcrypto/TrieDB.h>
#include "TrieHash.h"
#include "MemTrie.h"
#include "TestHelper.h"
#include "../TestHelper.h"
using namespace std;
using namespace dev;

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

Loading…
Cancel
Save