Browse Source

Merge branch 'develop' of https://github.com/ethereum/cpp-ethereum into

bc_rf

Conflicts:
	libethereum/BlockChainSync.cpp
	libethereum/BlockChainSync.h
cl-refactor
arkpar 10 years ago
parent
commit
d9b76cd804
  1. 7
      cmake/EthCompilerSettings.cmake
  2. 10
      eth/main.cpp
  3. 11
      ethminer/MinerAux.h
  4. 2
      libdevcore/Common.cpp
  5. 71
      libethash-cl/ethash_cl_miner.cpp
  6. 3
      libethash-cl/ethash_cl_miner.h
  7. 3
      libethcore/Common.h
  8. 3
      libethcore/Ethash.cpp
  9. 3
      libethcore/Ethash.h
  10. 6
      libethcore/Params.cpp
  11. 1
      libethereum/BlockChainSync.h
  12. 10
      libethereum/Client.cpp
  13. 2
      libethereum/EthereumHost.cpp
  14. 31
      libethereum/EthereumPeer.cpp
  15. 58
      libevm/VM.cpp
  16. 7
      libjsconsole/JSConsole.cpp
  17. 7
      libjsconsole/JSConsole.h
  18. 33
      libsolidity/AST.cpp
  19. 11
      libweb3jsonrpc/WebThreeStubServer.cpp
  20. 5
      libweb3jsonrpc/WebThreeStubServer.h
  21. 11
      test/libsolidity/SolidityNameAndTypeResolution.cpp

7
cmake/EthCompilerSettings.cmake

@ -34,11 +34,16 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# disable unknown pragma warning (4068)
# disable unsafe function warning (4996)
# disable decorated name length exceeded, name was truncated (4503)
# disable conversion from 'size_t' to 'type', possible loss of data (4267)
# disable qualifier applied to function type has no meaning; ignored (4180)
# disable C++ exception specification ignored except to indicate a function is not __declspec(nothrow) (4290)
# disable conversion from 'type1' to 'type2', possible loss of data (4244)
# disable forcing value to bool 'true' or 'false' (performance warning) (4800)
# disable warning C4535: calling _set_se_translator() requires /EHa (for boost tests)
# declare Windows XP requirement
# undefine windows.h MAX && MIN macros cause it cause conflicts with std::min && std::max functions
# define miniupnp static library
add_compile_options(/MP /EHsc /wd4068 /wd4996 /wd4503 -D_WIN32_WINNT=0x0501 /DNOMINMAX /DMINIUPNP_STATICLIB)
add_compile_options(/MP /EHsc /wd4068 /wd4996 /wd4503 /wd4267 /wd4180 /wd4290 /wd4244 /wd4800 -D_WIN32_WINNT=0x0501 /DNOMINMAX /DMINIUPNP_STATICLIB)
# disable empty object file warning
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221")
# warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/SAFESEH' specification

10
eth/main.cpp

@ -836,12 +836,13 @@ int main(int argc, char** argv)
cout << "Networking disabled. To start, use netstart or pass -b or a remote host." << endl;
#if ETH_JSONRPC || !ETH_TRUE
shared_ptr<WebThreeStubServer> jsonrpcServer;
shared_ptr<dev::WebThreeStubServer> jsonrpcServer;
unique_ptr<jsonrpc::AbstractServerConnector> jsonrpcConnector;
if (jsonrpc > -1)
{
jsonrpcConnector = unique_ptr<jsonrpc::AbstractServerConnector>(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads));
jsonrpcServer = shared_ptr<WebThreeStubServer>(new WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared<SimpleAccountHolder>([&](){ return web3.ethereum(); }, getAccountPassword, keyManager), vector<KeyPair>(), keyManager, *gasPricer));
jsonrpcServer = shared_ptr<dev::WebThreeStubServer>(new dev::WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared<SimpleAccountHolder>([&](){ return web3.ethereum(); }, getAccountPassword, keyManager), vector<KeyPair>(), keyManager, *gasPricer));
jsonrpcServer->setMiningBenefactorChanger([&](Address const& a) { beneficiary = a; });
jsonrpcServer->StartListening();
if (jsonAdmin.empty())
jsonAdmin = jsonrpcServer->newSession(SessionPermissions{{Priviledge::Admin}});
@ -996,7 +997,8 @@ int main(int argc, char** argv)
if (jsonrpc < 0)
jsonrpc = SensibleHttpPort;
jsonrpcConnector = unique_ptr<jsonrpc::AbstractServerConnector>(new jsonrpc::HttpServer(jsonrpc, "", "", SensibleHttpThreads));
jsonrpcServer = shared_ptr<WebThreeStubServer>(new WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared<SimpleAccountHolder>([&](){ return web3.ethereum(); }, getAccountPassword, keyManager), vector<KeyPair>(), keyManager, *gasPricer));
jsonrpcServer = shared_ptr<dev::WebThreeStubServer>(new dev::WebThreeStubServer(*jsonrpcConnector.get(), web3, make_shared<SimpleAccountHolder>([&](){ return web3.ethereum(); }, getAccountPassword, keyManager), vector<KeyPair>(), keyManager, *gasPricer));
jsonrpcServer->setMiningBenefactorChanger([&](Address const& a) { beneficiary = a; });
jsonrpcServer->StartListening();
if (jsonAdmin.empty())
jsonAdmin = jsonrpcServer->newSession(SessionPermissions{{Priviledge::Admin}});
@ -1743,7 +1745,7 @@ int main(int argc, char** argv)
JSConsole console(web3, make_shared<SimpleAccountHolder>([&](){return web3.ethereum();}, getAccountPassword, keyManager));
while (!g_exit)
{
console.repl();
console.readExpression();
stopMiningAfterXBlocks(c, n, mining);
}
#endif

11
ethminer/MinerAux.h

@ -134,8 +134,6 @@ public:
m_clAllowCPU = true;
else if (arg == "--cl-extragpu-mem" && i + 1 < argc)
m_extraGPUMemory = 1000000 * stol(argv[++i]);
else if (arg == "--force-single-chunk")
m_forceSingleChunk = true;
else if (arg == "--phone-home" && i + 1 < argc)
{
string m = argv[++i];
@ -273,7 +271,6 @@ public:
m_openclDevice,
m_clAllowCPU,
m_extraGPUMemory,
m_forceSingleChunk,
m_currentBlock
))
{
@ -318,10 +315,9 @@ public:
<< " --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
<< " --allow-opencl-cpu Allows CPU to be considered as an OpenCL device if the OpenCL platform supports it." << endl
<< " --list-devices List the detected OpenCL devices and exit." <<endl
<< " --current-block Let the miner know the current block number at configuration time. Will help determine DAG size and required GPU memory." <<endl
<< " --cl-extragpu-mem Set the memory (in MB) you believe your GPU requires for stuff other than mining. Windows rendering e.t.c.." <<endl
<< " --force-single-chunk Force DAG uploading in a single chunk against OpenCL's judgement. Use at your own risk." <<endl
<< " --list-devices List the detected OpenCL devices and exit." << endl
<< " --current-block Let the miner know the current block number at configuration time. Will help determine DAG size and required GPU memory." << endl
<< " --cl-extragpu-mem Set the memory (in MB) you believe your GPU requires for stuff other than mining. Windows rendering e.t.c.." << endl
;
}
@ -510,7 +506,6 @@ private:
unsigned m_miningThreads = UINT_MAX;
bool m_shouldListDevices = false;
bool m_clAllowCPU = false;
bool m_forceSingleChunk = false;
boost::optional<uint64_t> m_currentBlock;
// default value is 350MB of GPU memory for other stuff (windows system rendering, e.t.c.)
unsigned m_extraGPUMemory = 350000000;

2
libdevcore/Common.cpp

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

71
libethash-cl/ethash_cl_miner.cpp

@ -140,12 +140,10 @@ unsigned ethash_cl_miner::getNumDevices(unsigned _platformId)
bool ethash_cl_miner::configureGPU(
bool _allowCPU,
unsigned _extraGPUMemory,
bool _forceSingleChunk,
boost::optional<uint64_t> _currentBlock
)
{
s_allowCPU = _allowCPU;
s_forceSingleChunk = _forceSingleChunk;
s_extraRequiredGPUMem = _extraGPUMemory;
// by default let's only consider the DAG of the first epoch
uint64_t dagSize = _currentBlock ? ethash_get_datasize(*_currentBlock) : 1073739904U;
@ -174,7 +172,6 @@ bool ethash_cl_miner::configureGPU(
}
bool ethash_cl_miner::s_allowCPU = false;
bool ethash_cl_miner::s_forceSingleChunk = false;
unsigned ethash_cl_miner::s_extraRequiredGPUMem;
bool ethash_cl_miner::searchForAllDevices(function<bool(cl::Device const&)> _callback)
@ -288,23 +285,6 @@ bool ethash_cl_miner::init(
string device_version = device.getInfo<CL_DEVICE_VERSION>();
ETHCL_LOG("Using device: " << device.getInfo<CL_DEVICE_NAME>().c_str() << "(" << device_version.c_str() << ")");
// configure chunk number depending on max allocateable memory
cl_ulong result;
device.getInfo(CL_DEVICE_MAX_MEM_ALLOC_SIZE, &result);
if (s_forceSingleChunk || result >= _dagSize)
{
m_dagChunksNum = 1;
ETHCL_LOG(
((result <= _dagSize && s_forceSingleChunk) ? "Forcing single chunk. Good luck!\n" : "") <<
"Using 1 big chunk. Max OpenCL allocateable memory is " << result
);
}
else
{
m_dagChunksNum = 4;
ETHCL_LOG("Using 4 chunks. Max OpenCL allocateable memory is " << result);
}
if (strncmp("OpenCL 1.0", device_version.c_str(), 10) == 0)
{
ETHCL_LOG("OpenCL 1.0 is not supported.");
@ -341,31 +321,32 @@ bool ethash_cl_miner::init(
ETHCL_LOG("Printing program log");
ETHCL_LOG(program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device).c_str());
}
catch (cl::Error err)
catch (cl::Error const& err)
{
ETHCL_LOG(program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device).c_str());
return false;
}
if (m_dagChunksNum == 1)
{
ETHCL_LOG("Loading single big chunk kernels");
m_hash_kernel = cl::Kernel(program, "ethash_hash");
m_search_kernel = cl::Kernel(program, "ethash_search");
}
else
{
ETHCL_LOG("Loading chunk kernels");
m_hash_kernel = cl::Kernel(program, "ethash_hash_chunks");
m_search_kernel = cl::Kernel(program, "ethash_search_chunks");
}
// create buffer for dag
if (m_dagChunksNum == 1)
try
{
ETHCL_LOG("Creating one big buffer");
m_dagChunksNum = 1;
m_dagChunks.push_back(cl::Buffer(m_context, CL_MEM_READ_ONLY, _dagSize));
ETHCL_LOG("Created one big buffer for the DAG");
}
else
catch (cl::Error const& err)
{
int errCode = err.err();
if (errCode != CL_INVALID_BUFFER_SIZE || errCode != CL_MEM_OBJECT_ALLOCATION_FAILURE)
ETHCL_LOG("Allocating single buffer failed with: " << err.what() << "(" << errCode << ")");
cl_ulong result;
device.getInfo(CL_DEVICE_MAX_MEM_ALLOC_SIZE, &result);
ETHCL_LOG(
"Failed to allocate 1 big chunk. Max allocateable memory is "
<< result << ". Trying to allocate 4 chunks."
);
// The OpenCL kernel has a hard coded number of 4 chunks at the moment
m_dagChunksNum = 4;
for (unsigned i = 0; i < m_dagChunksNum; i++)
{
// TODO Note: If we ever change to _dagChunksNum other than 4, then the size would need recalculation
@ -376,6 +357,20 @@ bool ethash_cl_miner::init(
(i == 3) ? (_dagSize - 3 * ((_dagSize >> 9) << 7)) : (_dagSize >> 9) << 7
));
}
}
if (m_dagChunksNum == 1)
{
ETHCL_LOG("Loading single big chunk kernels");
m_hash_kernel = cl::Kernel(program, "ethash_hash");
m_search_kernel = cl::Kernel(program, "ethash_search");
}
else
{
ETHCL_LOG("Loading chunk kernels");
m_hash_kernel = cl::Kernel(program, "ethash_hash_chunks");
m_search_kernel = cl::Kernel(program, "ethash_search_chunks");
}
// create buffer for header
ETHCL_LOG("Creating buffer for header.");
@ -410,7 +405,7 @@ bool ethash_cl_miner::init(
m_search_buf[i] = cl::Buffer(m_context, CL_MEM_WRITE_ONLY, (c_max_search_results + 1) * sizeof(uint32_t));
}
}
catch (cl::Error err)
catch (cl::Error const& err)
{
ETHCL_LOG(err.what() << "(" << err.err() << ")");
return false;
@ -504,7 +499,7 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook
pre_return_event.wait();
#endif
}
catch (cl::Error err)
catch (cl::Error const& err)
{
ETHCL_LOG(err.what() << "(" << err.err() << ")");
}

3
libethash-cl/ethash_cl_miner.h

@ -44,7 +44,6 @@ public:
static bool configureGPU(
bool _allowCPU,
unsigned _extraGPUMemory,
bool _forceSingleChunk,
boost::optional<uint64_t> _currentBlock
);
@ -79,8 +78,6 @@ private:
unsigned m_workgroup_size;
bool m_opencl_1_1;
/// Force dag upload to GPU in a single chunk even if OpenCL thinks you can't do it. Use at your own risk.
static bool s_forceSingleChunk;
/// Allow CPU to appear as an OpenCL device or not. Default is false
static bool s_allowCPU;
/// GPU memory required for other things, like window rendering e.t.c.

3
libethcore/Common.h

@ -47,7 +47,8 @@ extern const unsigned c_databaseVersion;
enum class Network
{
Olympic = 0,
Frontier = 1
Frontier = 1,
Turbo = 2
};
extern const Network c_network;

3
libethcore/Ethash.cpp

@ -389,13 +389,12 @@ bool Ethash::GPUMiner::configureGPU(
unsigned _deviceId,
bool _allowCPU,
unsigned _extraGPUMemory,
bool _forceSingleChunk,
boost::optional<uint64_t> _currentBlock
)
{
s_platformId = _platformId;
s_deviceId = _deviceId;
return ethash_cl_miner::configureGPU(_allowCPU, _extraGPUMemory, _forceSingleChunk, _currentBlock);
return ethash_cl_miner::configureGPU(_allowCPU, _extraGPUMemory, _currentBlock);
}
#endif

3
libethcore/Ethash.h

@ -88,7 +88,7 @@ public:
static unsigned instances() { return s_numInstances > 0 ? s_numInstances : std::thread::hardware_concurrency(); }
static std::string platformInfo();
static void listDevices() {}
static bool configureGPU(unsigned, unsigned, bool, unsigned, bool, boost::optional<uint64_t>) { return false; }
static bool configureGPU(unsigned, unsigned, bool, unsigned, boost::optional<uint64_t>) { return false; }
static void setNumInstances(unsigned _instances) { s_numInstances = std::min<unsigned>(_instances, std::thread::hardware_concurrency()); }
protected:
void kickOff() override
@ -122,7 +122,6 @@ public:
unsigned _deviceId,
bool _allowCPU,
unsigned _extraGPUMemory,
bool _forceSingleChunk,
boost::optional<uint64_t> _currentBlock
);
static void setNumInstances(unsigned _instances) { s_numInstances = std::min<unsigned>(_instances, getNumDevices()); }

6
libethcore/Params.cpp

@ -31,12 +31,12 @@ namespace eth
//--- BEGIN: AUTOGENERATED FROM github.com/ethereum/common/params.json
u256 const c_genesisDifficulty = 131072;
u256 const c_maximumExtraDataSize = 1024;
u256 const c_genesisGasLimit = 3141592;
u256 const c_minGasLimit = 125000;
u256 const c_genesisGasLimit = c_network == Network::Turbo ? 100000000 : 3141592;
u256 const c_minGasLimit = c_network == Network::Turbo ? 100000000 : 125000;
u256 const c_gasLimitBoundDivisor = 1024;
u256 const c_minimumDifficulty = 131072;
u256 const c_difficultyBoundDivisor = 2048;
u256 const c_durationLimit = c_network == Network::Olympic ? 8 : 12;
u256 const c_durationLimit = c_network == Network::Turbo ? 2 : c_network == Network::Olympic ? 8 : 12;
//--- END: AUTOGENERATED FROM /feeStructure.json
}

1
libethereum/BlockChainSync.h

@ -114,6 +114,7 @@ protected:
/// Request blocks from peer if needed
void requestBlocks(EthereumPeer* _peer);
protected:
Handler m_bqRoomAvailable; ///< Triggered once block queue
mutable RecursiveMutex x_sync;
SyncState m_state = SyncState::Idle; ///< Current sync state

10
libethereum/Client.cpp

@ -673,10 +673,10 @@ void Client::onChainChanged(ImportRoute const& _ir)
// insert transactions that we are declaring the dead part of the chain
for (auto const& h: _ir.deadBlocks)
{
clog(ClientNote) << "Dead block:" << h;
clog(ClientTrace) << "Dead block:" << h;
for (auto const& t: m_bc.transactions(h))
{
clog(ClientNote) << "Resubmitting dead-block transaction " << Transaction(t, CheckTransaction::None);
clog(ClientTrace) << "Resubmitting dead-block transaction " << Transaction(t, CheckTransaction::None);
m_tq.import(t, TransactionQueue::ImportCallback(), IfDropped::Retry);
}
}
@ -684,10 +684,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.liveBlocks)
{
clog(ClientChat) << "Live block:" << h;
clog(ClientTrace) << "Live block:" << h;
for (auto const& th: m_bc.transactionHashes(h))
{
clog(ClientNote) << "Safely dropping transaction " << th;
clog(ClientTrace) << "Safely dropping transaction " << th;
m_tq.drop(th);
}
}
@ -723,7 +723,7 @@ void Client::onChainChanged(ImportRoute const& _ir)
DEV_READ_GUARDED(x_postMine)
for (auto const& t: m_postMine.pending())
{
clog(ClientNote) << "Resubmitting post-mine transaction " << t;
clog(ClientTrace) << "Resubmitting post-mine transaction " << t;
auto ir = m_tq.import(t, TransactionQueue::ImportCallback(), IfDropped::Retry);
if (ir != ImportResult::Success)
onTransactionQueueReady();

2
libethereum/EthereumHost.cpp

@ -296,7 +296,7 @@ void EthereumHost::onPeerTransactions(EthereumPeer* _peer, RLP const& _r)
unsigned itemCount = _r.itemCount();
clog(NetAllDetail) << "Transactions (" << dec << itemCount << "entries)";
Guard l(_peer->x_knownTransactions);
for (unsigned i = 0; i < itemCount; ++i)
for (unsigned i = 0; i < min<unsigned>(itemCount, 256); ++i) // process 256 transactions at most. TODO: much better solution.
{
auto h = sha3(_r[i].data());
_peer->m_knownTransactions.insert(h);

31
libethereum/EthereumPeer.cpp

@ -37,6 +37,18 @@ using namespace dev;
using namespace dev::eth;
using namespace p2p;
string toString(Asking _a)
{
switch (_a)
{
case Asking::Blocks: return "Blocks";
case Asking::Hashes: return "Hashes";
case Asking::Nothing: return "Nothing";
case Asking::State: return "State";
}
return "?";
}
EthereumPeer::EthereumPeer(Session* _s, HostCapabilityFace* _h, unsigned _i, CapDesc const& _cap):
Capability(_s, _h, _i),
m_sub(host()->downloadMan()),
@ -49,6 +61,11 @@ EthereumPeer::EthereumPeer(Session* _s, HostCapabilityFace* _h, unsigned _i, Cap
EthereumPeer::~EthereumPeer()
{
if (m_asking != Asking::Nothing)
{
cnote << "Peer aborting while being asked for " << ::toString(m_asking);
setRude();
}
abortSync();
}
@ -65,7 +82,9 @@ unsigned EthereumPeer::askOverride() const
void EthereumPeer::setRude()
{
auto old = askOverride();
repMan().setData(*session(), name(), rlp(askOverride() / 2 + 1));
cnote << "Rude behaviour; askOverride now" << askOverride() << ", was" << old;
repMan().noteRude(*session(), name());
session()->addNote("manners", "RUDE");
}
@ -84,18 +103,6 @@ EthereumHost* EthereumPeer::host() const
* Possible asking/syncing states for two peers:
*/
string toString(Asking _a)
{
switch (_a)
{
case Asking::Blocks: return "Blocks";
case Asking::Hashes: return "Hashes";
case Asking::Nothing: return "Nothing";
case Asking::State: return "State";
}
return "?";
}
void EthereumPeer::setIdle()
{
setAsking(Asking::Nothing);

58
libevm/VM.cpp

@ -202,6 +202,24 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
return nextPC;
};
auto copyDataToMemory = [](bytesConstRef _data, decltype(m_stack)& _stack, decltype(m_temp)& _memory)
{
auto offset = static_cast<size_t>(_stack.back());
_stack.pop_back();
bigint bigIndex = _stack.back();
auto index = static_cast<size_t>(bigIndex);
_stack.pop_back();
auto size = static_cast<size_t>(_stack.back());
_stack.pop_back();
size_t sizeToBeCopied = bigIndex + size > _data.size() ? _data.size() < bigIndex ? 0 : _data.size() - index : size;
if (sizeToBeCopied > 0)
std::memcpy(_memory.data() + offset, _data.data() + index, sizeToBeCopied);
if (size > sizeToBeCopied)
std::memset(_memory.data() + offset + sizeToBeCopied, 0, size - sizeToBeCopied);
};
m_steps = 0;
for (auto nextPC = m_curPC + 1; true; m_curPC = nextPC, nextPC = m_curPC + 1, ++m_steps)
{
@ -364,44 +382,16 @@ bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
m_stack.back() = _ext.codeAt(asAddress(m_stack.back())).size();
break;
case Instruction::CALLDATACOPY:
case Instruction::CODECOPY:
case Instruction::EXTCODECOPY:
{
Address a;
if (inst == Instruction::EXTCODECOPY)
{
a = asAddress(m_stack.back());
m_stack.pop_back();
}
unsigned offset = (unsigned)m_stack.back();
m_stack.pop_back();
u256 index = m_stack.back();
m_stack.pop_back();
unsigned size = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned sizeToBeCopied;
switch(inst)
{
case Instruction::CALLDATACOPY:
sizeToBeCopied = index + (bigint)size > (u256)_ext.data.size() ? (u256)_ext.data.size() < index ? 0 : _ext.data.size() - (unsigned)index : size;
memcpy(m_temp.data() + offset, _ext.data.data() + (unsigned)index, sizeToBeCopied);
copyDataToMemory(_ext.data, m_stack, m_temp);
break;
case Instruction::CODECOPY:
sizeToBeCopied = index + (bigint)size > (u256)_ext.code.size() ? (u256)_ext.code.size() < index ? 0 : _ext.code.size() - (unsigned)index : size;
memcpy(m_temp.data() + offset, _ext.code.data() + (unsigned)index, sizeToBeCopied);
copyDataToMemory(&_ext.code, m_stack, m_temp);
break;
case Instruction::EXTCODECOPY:
sizeToBeCopied = index + (bigint)size > (u256)_ext.codeAt(a).size() ? (u256)_ext.codeAt(a).size() < index ? 0 : _ext.codeAt(a).size() - (unsigned)index : size;
memcpy(m_temp.data() + offset, _ext.codeAt(a).data() + (unsigned)index, sizeToBeCopied);
break;
default:
// this is unreachable, but if someone introduces a bug in the future, he may get here.
assert(false);
BOOST_THROW_EXCEPTION(InvalidOpcode() << errinfo_comment("CALLDATACOPY, CODECOPY or EXTCODECOPY instruction requested."));
break;
}
memset(m_temp.data() + offset + sizeToBeCopied, 0, size - sizeToBeCopied);
break;
{
auto a = asAddress(m_stack.back());
m_stack.pop_back();
copyDataToMemory(&_ext.codeAt(a), m_stack, m_temp);
}
case Instruction::GASPRICE:
m_stack.push_back(_ext.gasPrice);

7
libjsconsole/JSConsole.cpp

@ -39,12 +39,11 @@ JSConsole::JSConsole(WebThreeDirect& _web3, shared_ptr<AccountHolder> const& _ac
m_printer(m_engine)
{
m_jsonrpcConnector.reset(new JSV8Connector(m_engine));
m_jsonrpcServer.reset(new WebThreeStubServer(*m_jsonrpcConnector.get(), _web3, _accounts, vector<KeyPair>()));
(void)_web3; (void)_accounts;
// m_jsonrpcServer.reset(new WebThreeStubServer(*m_jsonrpcConnector.get(), _web3, _accounts, vector<KeyPair>()));
}
JSConsole::~JSConsole() {}
void JSConsole::repl() const
void JSConsole::readExpression() const
{
string cmd = "";
g_logPost = [](std::string const& a, char const*) { cout << "\r \r" << a << endl << flush; rl_forced_update_display(); };

7
libjsconsole/JSConsole.h

@ -25,7 +25,7 @@
#include <libjsengine/JSV8Engine.h>
#include <libjsengine/JSV8Printer.h>
class WebThreeStubServer;
namespace dev { class WebThreeStubServer; }
namespace jsonrpc { class AbstractServerConnector; }
namespace dev
@ -39,15 +39,14 @@ class JSConsole
{
public:
JSConsole(WebThreeDirect& _web3, std::shared_ptr<AccountHolder> const& _accounts);
~JSConsole();
void repl() const;
void readExpression() const;
private:
std::string promptForIndentionLevel(int _i) const;
JSV8Engine m_engine;
JSV8Printer m_printer;
std::unique_ptr<WebThreeStubServer> m_jsonrpcServer;
std::unique_ptr<dev::WebThreeStubServer> m_jsonrpcServer;
std::unique_ptr<jsonrpc::AbstractServerConnector> m_jsonrpcConnector;
};

33
libsolidity/AST.cpp

@ -21,6 +21,7 @@
*/
#include <algorithm>
#include <functional>
#include <boost/range/adaptor/reversed.hpp>
#include <libsolidity/Utils.h>
#include <libsolidity/AST.h>
@ -434,23 +435,29 @@ void StructDefinition::checkMemberTypes() const
void StructDefinition::checkRecursion() const
{
set<StructDefinition const*> definitionsSeen;
vector<StructDefinition const*> queue = {this};
while (!queue.empty())
using StructPointer = StructDefinition const*;
using StructPointersSet = set<StructPointer>;
function<void(StructPointer,StructPointersSet const&)> check = [&](StructPointer _struct, StructPointersSet const& _parents)
{
StructDefinition const* def = queue.back();
queue.pop_back();
if (definitionsSeen.count(def))
BOOST_THROW_EXCEPTION(ParserError() << errinfo_sourceLocation(def->getLocation())
<< errinfo_comment("Recursive struct definition."));
definitionsSeen.insert(def);
for (ASTPointer<VariableDeclaration> const& member: def->getMembers())
if (_parents.count(_struct))
BOOST_THROW_EXCEPTION(
ParserError() <<
errinfo_sourceLocation(_struct->getLocation()) <<
errinfo_comment("Recursive struct definition.")
);
set<StructDefinition const*> parents = _parents;
parents.insert(_struct);
for (ASTPointer<VariableDeclaration> const& member: _struct->getMembers())
if (member->getType()->getCategory() == Type::Category::Struct)
{
UserDefinedTypeName const& typeName = dynamic_cast<UserDefinedTypeName const&>(*member->getTypeName());
queue.push_back(&dynamic_cast<StructDefinition const&>(*typeName.getReferencedDeclaration()));
}
auto const& typeName = dynamic_cast<UserDefinedTypeName const&>(*member->getTypeName());
check(
&dynamic_cast<StructDefinition const&>(*typeName.getReferencedDeclaration()),
parents
);
}
};
check(this, {});
}
TypePointer EnumDefinition::getType(ContractDefinition const*) const

11
libweb3jsonrpc/WebThreeStubServer.cpp

@ -205,7 +205,16 @@ Json::Value WebThreeStubServer::admin_eth_newAccount(Json::Value const& _info, s
bool WebThreeStubServer::admin_eth_setMiningBenefactor(std::string const& _uuidOrAddress, std::string const& _session)
{
ADMIN;
(void)_uuidOrAddress;
Address a;
h128 uuid = fromUUID(_uuidOrAddress);
if (uuid)
a = m_keyMan.address(uuid);
else if (isHash<Address>(_uuidOrAddress))
a = Address(_uuidOrAddress);
else
throw jsonrpc::JsonRpcException("Invalid UUID or address");
if (m_setMiningBenefactor)
m_setMiningBenefactor(a);
return true;
}

5
libweb3jsonrpc/WebThreeStubServer.h

@ -60,6 +60,8 @@ public:
std::string newSession(SessionPermissions const& _p);
void addSession(std::string const& _session, SessionPermissions const& _p) { m_sessions[_session] = _p; }
virtual void setMiningBenefactorChanger(std::function<void(Address const&)> const& _f) { m_setMiningBenefactor = _f; }
private:
virtual bool hasPriviledgeLevel(std::string const& _session, Priviledge _l) const override { auto it = m_sessions.find(_session); return it != m_sessions.end() && it->second.priviledges.count(_l); }
@ -80,9 +82,9 @@ private:
virtual std::string admin_eth_blockQueueFirstUnknown(std::string const& _session) override;
virtual bool admin_eth_blockQueueRetryUnknown(std::string const& _session) override;
virtual bool admin_eth_setMiningBenefactor(std::string const& _uuidOrAddress, std::string const& _session) override;
virtual Json::Value admin_eth_allAccounts(std::string const& _session) override;
virtual Json::Value admin_eth_newAccount(const Json::Value& _info, std::string const& _session) override;
virtual bool admin_eth_setMiningBenefactor(std::string const& _uuidOrAddress, std::string const& _session) override;
virtual Json::Value admin_eth_inspect(std::string const& _address, std::string const& _session) override;
virtual Json::Value admin_eth_reprocess(std::string const& _blockNumberOrHash, std::string const& _session) override;
virtual Json::Value admin_eth_vmTrace(std::string const& _blockNumberOrHash, int _txIndex, std::string const& _session) override;
@ -101,6 +103,7 @@ private:
leveldb::WriteOptions m_writeOptions;
leveldb::DB* m_db;
std::function<void(Address const&)> m_setMiningBenefactor;
std::unordered_map<std::string, SessionPermissions> m_sessions;
};

11
test/libsolidity/SolidityNameAndTypeResolution.cpp

@ -190,6 +190,17 @@ BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive)
BOOST_CHECK_THROW(parseTextAndResolveNames(text), ParserError);
}
BOOST_AUTO_TEST_CASE(struct_definition_not_really_recursive)
{
char const* text = R"(
contract test {
struct s1 { uint a; }
struct s2 { s1 x; s1 y; }
}
)";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(struct_definition_recursion_via_mapping)
{
char const* text = "contract test {\n"

Loading…
Cancel
Save