Browse Source

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

bc

Conflicts:
	libethereum/Executive.cpp
cl-refactor
arkpar 10 years ago
parent
commit
343a361d68
  1. 8
      alethzero/MainWin.cpp
  2. 2
      alethzero/Transact.cpp
  3. 39
      ethkey/KeyAux.h
  4. 7
      ethminer/MinerAux.h
  5. 4
      evmjit/libevmjit-cpp/JitVM.cpp
  6. 2
      evmjit/libevmjit-cpp/JitVM.h
  7. 2
      libdevcore/Common.cpp
  8. 52
      libdevcore/CommonData.cpp
  9. 2
      libdevcore/CommonData.h
  10. 2
      libdevcrypto/Common.cpp
  11. 2
      libdevcrypto/Common.h
  12. 2
      libdevcrypto/SecretStore.cpp
  13. 361
      libethash-cl/ethash_cl_miner.cpp
  14. 15
      libethash-cl/ethash_cl_miner.h
  15. 142
      libethash-cl/ethash_cl_miner_kernel.cl
  16. 3
      libethcore/Ethash.cpp
  17. 3
      libethcore/Ethash.h
  18. 23
      libethcore/KeyManager.cpp
  19. 11
      libethcore/KeyManager.h
  20. 3
      libethereum/Client.cpp
  21. 6
      libethereum/CommonNet.h
  22. 4
      libethereum/EthereumHost.cpp
  23. 4
      libethereum/EthereumPeer.cpp
  24. 65
      libethereum/Executive.cpp
  25. 15
      libethereum/Executive.h
  26. 1
      libethereum/ExtVM.cpp
  27. 55
      libethereum/Precompiled.cpp
  28. 2
      libethereum/Precompiled.h
  29. 4
      libethereum/State.cpp
  30. 17
      libethereum/Transaction.h
  31. 4
      libevm/SmartVM.cpp
  32. 2
      libevm/SmartVM.h
  33. 9
      libevm/VM.cpp
  34. 2
      libevm/VM.h
  35. 18
      libevm/VMFace.h
  36. 4
      libevmasm/CommonSubexpressionEliminator.cpp
  37. 5
      libsolidity/ArrayUtils.cpp
  38. 2
      libsolidity/Compiler.cpp
  39. 11
      libsolidity/CompilerUtils.cpp
  40. 2
      libsolidity/ExpressionCompiler.cpp
  41. 26
      libsolidity/LValue.cpp
  42. 5
      mix/MixClient.cpp
  43. 2
      solc/CommandLineInterface.cpp
  44. 4
      test/fuzzTesting/checkRandomVMTest.cpp
  45. 2
      test/fuzzTesting/createRandomVMTest.cpp
  46. 4
      test/libevm/vm.cpp
  47. 4
      test/libsolidity/solidityExecutionFramework.h

8
alethzero/MainWin.cpp

@ -2115,14 +2115,14 @@ void Main::on_reencryptKey_triggered()
auto pw = [&](){
auto p = QInputDialog::getText(this, "Re-Encrypt Key", "Enter the original password for this key.\nHint: " + QString::fromStdString(m_keyManager.hint(a)), QLineEdit::Password, QString()).toStdString();
if (p.empty())
throw UnknownPassword();
throw PasswordUnknown();
return p;
};
while (!(password.empty() ? m_keyManager.recode(a, SemanticPassword::Master, pw, kdf) : m_keyManager.recode(a, password, hint, pw, kdf)))
if (QMessageBox::question(this, "Re-Encrypt Key", "Password given is incorrect. Would you like to try again?", QMessageBox::Retry, QMessageBox::Cancel) == QMessageBox::Cancel)
return;
}
catch (UnknownPassword&) {}
catch (PasswordUnknown&) {}
}
}
@ -2138,13 +2138,13 @@ void Main::on_reencryptAll_triggered()
while (!m_keyManager.recode(a, SemanticPassword::Existing, [&](){
auto p = QInputDialog::getText(nullptr, "Re-Encrypt Key", QString("Enter the original password for key %1.\nHint: %2").arg(QString::fromStdString(pretty(a))).arg(QString::fromStdString(m_keyManager.hint(a))), QLineEdit::Password, QString()).toStdString();
if (p.empty())
throw UnknownPassword();
throw PasswordUnknown();
return p;
}, (KDF)kdfs.indexOf(kdf)))
if (QMessageBox::question(this, "Re-Encrypt Key", "Password given is incorrect. Would you like to try again?", QMessageBox::Retry, QMessageBox::Cancel) == QMessageBox::Cancel)
return;
}
catch (UnknownPassword&) {}
catch (PasswordUnknown&) {}
}
void Main::on_go_triggered()

2
alethzero/Transact.cpp

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

39
ethkey/KeyAux.h

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

7
ethminer/MinerAux.h

@ -127,6 +127,10 @@ public:
cerr << "Bad " << arg << " option: " << argv[i] << endl;
throw BadArgument();
}
else if (arg == "--use-chunks")
{
dagChunks = 4;
}
else if (arg == "--phone-home" && i + 1 < argc)
{
string m = argv[++i];
@ -264,6 +268,7 @@ public:
ProofOfWork::GPUMiner::setDefaultPlatform(openclPlatform);
ProofOfWork::GPUMiner::setDefaultDevice(openclDevice);
ProofOfWork::GPUMiner::setNumInstances(miningThreads);
ProofOfWork::GPUMiner::setDagChunks(dagChunks);
}
if (mode == OperationMode::DAGInit)
doInitDAG(initDAG);
@ -301,6 +306,7 @@ public:
<< " --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
<< " --use-chunks When using GPU mining upload the DAG to the GPU in 4 chunks. " << endl
;
}
@ -488,6 +494,7 @@ private:
unsigned openclPlatform = 0;
unsigned openclDevice = 0;
unsigned miningThreads = UINT_MAX;
unsigned dagChunks = 1;
/// DAG initialisation param.
unsigned initDAG = 0;

4
evmjit/libevmjit-cpp/JitVM.cpp

@ -18,7 +18,7 @@ namespace eth
extern "C" void env_sload(); // fake declaration for linker symbol stripping workaround, see a call below
bytesConstRef JitVM::go(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _step)
bytesConstRef JitVM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
{
using namespace jit;
@ -33,7 +33,7 @@ bytesConstRef JitVM::go(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp, ui
{
cwarn << "Execution rejected by EVM JIT (gas limit: " << io_gas << "), executing with interpreter";
m_fallbackVM = VMFactory::create(VMKind::Interpreter);
return m_fallbackVM->go(io_gas, _ext, _onOp, _step);
return m_fallbackVM->execImpl(io_gas, _ext, _onOp);
}
m_data.gas = static_cast<decltype(m_data.gas)>(io_gas);

2
evmjit/libevmjit-cpp/JitVM.h

@ -11,7 +11,7 @@ namespace eth
class JitVM: public VMFace
{
public:
virtual bytesConstRef go(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final;
virtual bytesConstRef execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp) override final;
private:
jit::RuntimeData m_data;

2
libdevcore/Common.cpp

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

52
libdevcore/CommonData.cpp

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

2
libdevcore/CommonData.h

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

2
libdevcrypto/Common.cpp

@ -37,7 +37,7 @@ using namespace dev::crypto;
static Secp256k1 s_secp256k1;
bool dev::SignatureStruct::isValid() const
bool dev::SignatureStruct::isValid() const noexcept
{
if (v > 1 ||
r >= h256("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") ||

2
libdevcrypto/Common.h

@ -51,7 +51,7 @@ struct SignatureStruct
operator Signature() const { return *(h520 const*)this; }
/// @returns true if r,s,v values are valid, otherwise false
bool isValid() const;
bool isValid() const noexcept;
h256 r;
h256 s;

2
libdevcrypto/SecretStore.cpp

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

361
libethash-cl/ethash_cl_miner.cpp

@ -24,6 +24,7 @@
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <assert.h>
#include <queue>
@ -173,195 +174,249 @@ void ethash_cl_miner::finish()
m_queue.finish();
}
bool ethash_cl_miner::init(uint8_t const* _dag, uint64_t _dagSize, unsigned workgroup_size, unsigned _platformId, unsigned _deviceId)
bool ethash_cl_miner::init(
uint8_t const* _dag,
uint64_t _dagSize,
unsigned workgroup_size,
unsigned _platformId,
unsigned _deviceId,
unsigned _dagChunksNum
)
{
// for now due to the .cl kernels we can only have either 1 big chunk or 4 chunks
assert(_dagChunksNum == 1 || _dagChunksNum == 4);
// now create the number of chunk buffers
m_dagChunksNum = _dagChunksNum;
// get all platforms
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
if (platforms.empty())
try
{
ETHCL_LOG("No OpenCL platforms found.");
return false;
}
// use selected platform
_platformId = std::min<unsigned>(_platformId, platforms.size() - 1);
ETHCL_LOG("Using platform: " << platforms[_platformId].getInfo<CL_PLATFORM_NAME>().c_str());
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
if (platforms.empty())
{
ETHCL_LOG("No OpenCL platforms found.");
return false;
}
// get GPU device of the default platform
std::vector<cl::Device> devices;
platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices);
if (devices.empty())
{
ETHCL_LOG("No OpenCL devices found.");
return false;
}
// use selected platform
_platformId = std::min<unsigned>(_platformId, platforms.size() - 1);
ETHCL_LOG("Using platform: " << platforms[_platformId].getInfo<CL_PLATFORM_NAME>().c_str());
// use selected device
cl::Device& device = devices[std::min<unsigned>(_deviceId, devices.size() - 1)];
std::string device_version = device.getInfo<CL_DEVICE_VERSION>();
ETHCL_LOG("Using device: " << device.getInfo<CL_DEVICE_NAME>().c_str() << "(" << device_version.c_str() << ")");
// get GPU device of the default platform
std::vector<cl::Device> devices;
platforms[_platformId].getDevices(CL_DEVICE_TYPE_ALL, &devices);
if (devices.empty())
{
ETHCL_LOG("No OpenCL devices found.");
return false;
}
if (strncmp("OpenCL 1.0", device_version.c_str(), 10) == 0)
{
ETHCL_LOG("OpenCL 1.0 is not supported.");
return false;
}
if (strncmp("OpenCL 1.1", device_version.c_str(), 10) == 0)
m_opencl_1_1 = true;
// use selected device
cl::Device& device = devices[std::min<unsigned>(_deviceId, devices.size() - 1)];
std::string device_version = device.getInfo<CL_DEVICE_VERSION>();
ETHCL_LOG("Using device: " << device.getInfo<CL_DEVICE_NAME>().c_str() << "(" << device_version.c_str() << ")");
// create context
m_context = cl::Context(std::vector<cl::Device>(&device, &device + 1));
m_queue = cl::CommandQueue(m_context, device);
if (strncmp("OpenCL 1.0", device_version.c_str(), 10) == 0)
{
ETHCL_LOG("OpenCL 1.0 is not supported.");
return false;
}
if (strncmp("OpenCL 1.1", device_version.c_str(), 10) == 0)
m_opencl_1_1 = true;
// create context
m_context = cl::Context(std::vector<cl::Device>(&device, &device + 1));
m_queue = cl::CommandQueue(m_context, device);
// use requested workgroup size, but we require multiple of 8
m_workgroup_size = ((workgroup_size + 7) / 8) * 8;
// patch source code
// note: ETHASH_CL_MINER_KERNEL is simply ethash_cl_miner_kernel.cl compiled
// into a byte array by bin2h.cmake. There is no need to load the file by hand in runtime
std::string code(ETHASH_CL_MINER_KERNEL, ETHASH_CL_MINER_KERNEL + ETHASH_CL_MINER_KERNEL_SIZE);
add_definition(code, "GROUP_SIZE", m_workgroup_size);
add_definition(code, "DAG_SIZE", (unsigned)(_dagSize / ETHASH_MIX_BYTES));
add_definition(code, "ACCESSES", ETHASH_ACCESSES);
add_definition(code, "MAX_OUTPUTS", c_max_search_results);
//debugf("%s", code.c_str());
// create miner OpenCL program
cl::Program::Sources sources;
sources.push_back({ code.c_str(), code.size() });
cl::Program program(m_context, sources);
try
{
program.build({ device });
ETHCL_LOG("Printing program log");
ETHCL_LOG(program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device).c_str());
}
catch (cl::Error err)
{
ETHCL_LOG(program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device).c_str());
return false;
}
if (_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");
}
// use requested workgroup size, but we require multiple of 8
m_workgroup_size = ((workgroup_size + 7) / 8) * 8;
// create buffer for dag
if (_dagChunksNum == 1)
{
ETHCL_LOG("Creating one big buffer");
m_dagChunks.push_back(cl::Buffer(m_context, CL_MEM_READ_ONLY, _dagSize));
}
else
for (unsigned i = 0; i < _dagChunksNum; i++)
{
// TODO Note: If we ever change to _dagChunksNum other than 4, then the size would need recalculation
ETHCL_LOG("Creating buffer for chunk " << i);
m_dagChunks.push_back(cl::Buffer(
m_context,
CL_MEM_READ_ONLY,
(i == 3) ? (_dagSize - 3 * ((_dagSize >> 9) << 7)) : (_dagSize >> 9) << 7
));
}
// patch source code
std::string code(ETHASH_CL_MINER_KERNEL, ETHASH_CL_MINER_KERNEL + ETHASH_CL_MINER_KERNEL_SIZE);
add_definition(code, "GROUP_SIZE", m_workgroup_size);
add_definition(code, "DAG_SIZE", (unsigned)(_dagSize / ETHASH_MIX_BYTES));
add_definition(code, "ACCESSES", ETHASH_ACCESSES);
add_definition(code, "MAX_OUTPUTS", c_max_search_results);
//debugf("%s", code.c_str());
// create buffer for header
ETHCL_LOG("Creating buffer for header.");
m_header = cl::Buffer(m_context, CL_MEM_READ_ONLY, 32);
// create miner OpenCL program
cl::Program::Sources sources;
sources.push_back({code.c_str(), code.size()});
if (_dagChunksNum == 1)
{
ETHCL_LOG("Mapping one big chunk.");
m_queue.enqueueWriteBuffer(m_dagChunks[0], CL_TRUE, 0, _dagSize, _dag);
}
else
{
// TODO Note: If we ever change to _dagChunksNum other than 4, then the size would need recalculation
void* dag_ptr[4];
for (unsigned i = 0; i < _dagChunksNum; i++)
{
ETHCL_LOG("Mapping chunk " << i);
dag_ptr[i] = m_queue.enqueueMapBuffer(m_dagChunks[i], true, m_opencl_1_1 ? CL_MAP_WRITE : CL_MAP_WRITE_INVALIDATE_REGION, 0, (i == 3) ? (_dagSize - 3 * ((_dagSize >> 9) << 7)) : (_dagSize >> 9) << 7);
}
for (unsigned i = 0; i < _dagChunksNum; i++)
{
memcpy(dag_ptr[i], (char *)_dag + i*((_dagSize >> 9) << 7), (i == 3) ? (_dagSize - 3 * ((_dagSize >> 9) << 7)) : (_dagSize >> 9) << 7);
m_queue.enqueueUnmapMemObject(m_dagChunks[i], dag_ptr[i]);
}
}
cl::Program program(m_context, sources);
try
{
program.build({device});
// create mining buffers
for (unsigned i = 0; i != c_num_buffers; ++i)
{
ETHCL_LOG("Creating mining buffer " << i);
m_hash_buf[i] = cl::Buffer(m_context, CL_MEM_WRITE_ONLY | (!m_opencl_1_1 ? CL_MEM_HOST_READ_ONLY : 0), 32 * c_hash_batch_size);
m_search_buf[i] = cl::Buffer(m_context, CL_MEM_WRITE_ONLY, (c_max_search_results + 1) * sizeof(uint32_t));
}
}
catch (cl::Error err)
{
ETHCL_LOG(program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device).c_str());
ETHCL_LOG(err.what() << "(" << err.err() << ")");
return false;
}
m_hash_kernel = cl::Kernel(program, "ethash_hash");
m_search_kernel = cl::Kernel(program, "ethash_search");
// create buffer for dag
m_dag = cl::Buffer(m_context, CL_MEM_READ_ONLY, _dagSize);
// create buffer for header
m_header = cl::Buffer(m_context, CL_MEM_READ_ONLY, 32);
// compute dag on CPU
try {
m_queue.enqueueWriteBuffer(m_dag, CL_TRUE, 0, _dagSize, _dag);
}
catch (...)
{
// didn't work. shitty driver. try allocating in CPU RAM and manually memcpying it.
void* dag_ptr = m_queue.enqueueMapBuffer(m_dag, true, m_opencl_1_1 ? CL_MAP_WRITE : CL_MAP_WRITE_INVALIDATE_REGION, 0, _dagSize);
memcpy(dag_ptr, _dag, _dagSize);
m_queue.enqueueUnmapMemObject(m_dag, dag_ptr);
}
// create mining buffers
for (unsigned i = 0; i != c_num_buffers; ++i)
{
m_hash_buf[i] = cl::Buffer(m_context, CL_MEM_WRITE_ONLY | (!m_opencl_1_1 ? CL_MEM_HOST_READ_ONLY : 0), 32*c_hash_batch_size);
m_search_buf[i] = cl::Buffer(m_context, CL_MEM_WRITE_ONLY, (c_max_search_results + 1) * sizeof(uint32_t));
}
return true;
}
void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook& hook)
{
struct pending_batch
try
{
uint64_t start_nonce;
unsigned buf;
};
std::queue<pending_batch> pending;
struct pending_batch
{
uint64_t start_nonce;
unsigned buf;
};
std::queue<pending_batch> pending;
uint32_t const c_zero = 0;
static uint32_t const c_zero = 0;
// update header constant buffer
m_queue.enqueueWriteBuffer(m_header, false, 0, 32, header);
for (unsigned i = 0; i != c_num_buffers; ++i)
m_queue.enqueueWriteBuffer(m_search_buf[i], false, 0, 4, &c_zero);
// update header constant buffer
m_queue.enqueueWriteBuffer(m_header, false, 0, 32, header);
for (unsigned i = 0; i != c_num_buffers; ++i)
m_queue.enqueueWriteBuffer(m_search_buf[i], false, 0, 4, &c_zero);
#if CL_VERSION_1_2 && 0
cl::Event pre_return_event;
if (!m_opencl_1_1)
m_queue.enqueueBarrierWithWaitList(NULL, &pre_return_event);
else
cl::Event pre_return_event;
if (!m_opencl_1_1)
m_queue.enqueueBarrierWithWaitList(NULL, &pre_return_event);
else
#endif
m_queue.finish();
/*
__kernel void ethash_combined_search(
__global hash32_t* g_hashes, // 0
__constant hash32_t const* g_header, // 1
__global hash128_t const* g_dag, // 2
ulong start_nonce, // 3
ulong target, // 4
uint isolate // 5
)
*/
m_search_kernel.setArg(1, m_header);
m_search_kernel.setArg(2, m_dag);
// pass these to stop the compiler unrolling the loops
m_search_kernel.setArg(4, target);
m_search_kernel.setArg(5, ~0u);
unsigned buf = 0;
std::random_device engine;
uint64_t start_nonce = std::uniform_int_distribution<uint64_t>()(engine);
for (; ; start_nonce += c_search_batch_size)
{
// supply output buffer to kernel
m_search_kernel.setArg(0, m_search_buf[buf]);
m_search_kernel.setArg(3, start_nonce);
// execute it!
m_queue.enqueueNDRangeKernel(m_search_kernel, cl::NullRange, c_search_batch_size, m_workgroup_size);
pending.push({start_nonce, buf});
buf = (buf + 1) % c_num_buffers;
// read results
if (pending.size() == c_num_buffers)
m_queue.finish();
unsigned argPos = 2;
m_search_kernel.setArg(1, m_header);
for (unsigned i = 0; i < m_dagChunksNum; ++i, ++argPos)
m_search_kernel.setArg(argPos, m_dagChunks[i]);
// pass these to stop the compiler unrolling the loops
m_search_kernel.setArg(argPos + 1, target);
m_search_kernel.setArg(argPos + 2, ~0u);
unsigned buf = 0;
std::random_device engine;
uint64_t start_nonce = std::uniform_int_distribution<uint64_t>()(engine);
for (;; start_nonce += c_search_batch_size)
{
pending_batch const& batch = pending.front();
// supply output buffer to kernel
m_search_kernel.setArg(0, m_search_buf[buf]);
if (m_dagChunksNum == 1)
m_search_kernel.setArg(3, start_nonce);
else
m_search_kernel.setArg(6, start_nonce);
// could use pinned host pointer instead
uint32_t* results = (uint32_t*)m_queue.enqueueMapBuffer(m_search_buf[batch.buf], true, CL_MAP_READ, 0, (1+c_max_search_results) * sizeof(uint32_t));
unsigned num_found = std::min<unsigned>(results[0], c_max_search_results);
// execute it!
m_queue.enqueueNDRangeKernel(m_search_kernel, cl::NullRange, c_search_batch_size, m_workgroup_size);
uint64_t nonces[c_max_search_results];
for (unsigned i = 0; i != num_found; ++i)
pending.push({ start_nonce, buf });
buf = (buf + 1) % c_num_buffers;
// read results
if (pending.size() == c_num_buffers)
{
nonces[i] = batch.start_nonce + results[i+1];
}
pending_batch const& batch = pending.front();
m_queue.enqueueUnmapMemObject(m_search_buf[batch.buf], results);
bool exit = num_found && hook.found(nonces, num_found);
exit |= hook.searched(batch.start_nonce, c_search_batch_size); // always report searched before exit
if (exit)
break;
// could use pinned host pointer instead
uint32_t* results = (uint32_t*)m_queue.enqueueMapBuffer(m_search_buf[batch.buf], true, CL_MAP_READ, 0, (1 + c_max_search_results) * sizeof(uint32_t));
unsigned num_found = std::min<unsigned>(results[0], c_max_search_results);
// reset search buffer if we're still going
if (num_found)
m_queue.enqueueWriteBuffer(m_search_buf[batch.buf], true, 0, 4, &c_zero);
uint64_t nonces[c_max_search_results];
for (unsigned i = 0; i != num_found; ++i)
nonces[i] = batch.start_nonce + results[i + 1];
pending.pop();
m_queue.enqueueUnmapMemObject(m_search_buf[batch.buf], results);
bool exit = num_found && hook.found(nonces, num_found);
exit |= hook.searched(batch.start_nonce, c_search_batch_size); // always report searched before exit
if (exit)
break;
// reset search buffer if we're still going
if (num_found)
m_queue.enqueueWriteBuffer(m_search_buf[batch.buf], true, 0, 4, &c_zero);
pending.pop();
}
}
}
// not safe to return until this is ready
// not safe to return until this is ready
#if CL_VERSION_1_2 && 0
if (!m_opencl_1_1)
pre_return_event.wait();
if (!m_opencl_1_1)
pre_return_event.wait();
#endif
}
catch (cl::Error err)
{
ETHCL_LOG(err.what() << "(" << err.err() << ")");
}
}

15
libethash-cl/ethash_cl_miner.h

@ -37,10 +37,20 @@ public:
static std::string platform_info(unsigned _platformId = 0, unsigned _deviceId = 0);
static bool haveSufficientGPUMemory(unsigned _platformId = 0);
bool init(uint8_t const* _dag, uint64_t _dagSize, unsigned workgroup_size = 64, unsigned _platformId = 0, unsigned _deviceId = 0);
bool init(
uint8_t const* _dag,
uint64_t _dagSize,
unsigned workgroup_size = 64,
unsigned _platformId = 0,
unsigned _deviceId = 0,
unsigned _dagChunksNum = 1
);
void finish();
void search(uint8_t const* header, uint64_t target, search_hook& hook);
void hash_chunk(uint8_t* ret, uint8_t const* header, uint64_t nonce, unsigned count);
void search_chunk(uint8_t const* header, uint64_t target, search_hook& hook);
private:
enum { c_max_search_results = 63, c_num_buffers = 2, c_hash_batch_size = 1024, c_search_batch_size = 1024*256 };
@ -48,7 +58,8 @@ private:
cl::CommandQueue m_queue;
cl::Kernel m_hash_kernel;
cl::Kernel m_search_kernel;
cl::Buffer m_dag;
unsigned m_dagChunksNum;
std::vector<cl::Buffer> m_dagChunks;
cl::Buffer m_header;
cl::Buffer m_hash_buf[c_num_buffers];
cl::Buffer m_search_buf[c_num_buffers];

142
libethash-cl/ethash_cl_miner_kernel.cl

@ -179,13 +179,13 @@ void keccak_f1600_no_absorb(ulong* a, uint in_size, uint out_size, uint isolate)
// much we try and help the compiler save VGPRs because it seems to throw
// that information away, hence the implementation of keccak here
// doesn't bother.
if (isolate)
if (isolate)
{
keccak_f1600_round((uint2*)a, r++, 25);
}
}
while (r < 23);
// final round optimised for digest size
keccak_f1600_round((uint2*)a, r++, out_size);
}
@ -232,7 +232,7 @@ hash64_t init_hash(__constant hash32_t const* header, ulong nonce, uint isolate)
hash64_t init;
uint const init_size = countof(init.ulongs);
uint const hash_size = countof(header->ulongs);
// sha3_512(header .. nonce)
ulong state[25];
copy(state, header->ulongs, hash_size);
@ -243,6 +243,40 @@ hash64_t init_hash(__constant hash32_t const* header, ulong nonce, uint isolate)
return init;
}
uint inner_loop_chunks(uint4 init, uint thread_id, __local uint* share, __global hash128_t const* g_dag, __global hash128_t const* g_dag1, __global hash128_t const* g_dag2, __global hash128_t const* g_dag3, uint isolate)
{
uint4 mix = init;
// share init0
if (thread_id == 0)
*share = mix.x;
barrier(CLK_LOCAL_MEM_FENCE);
uint init0 = *share;
uint a = 0;
do
{
bool update_share = thread_id == (a/4) % THREADS_PER_HASH;
#pragma unroll
for (uint i = 0; i != 4; ++i)
{
if (update_share)
{
uint m[4] = { mix.x, mix.y, mix.z, mix.w };
*share = fnv(init0 ^ (a+i), m[i]) % DAG_SIZE;
}
barrier(CLK_LOCAL_MEM_FENCE);
mix = fnv4(mix, *share>=3 * DAG_SIZE / 4 ? g_dag3[*share - 3 * DAG_SIZE / 4].uint4s[thread_id] : *share>=DAG_SIZE / 2 ? g_dag2[*share - DAG_SIZE / 2].uint4s[thread_id] : *share>=DAG_SIZE / 4 ? g_dag1[*share - DAG_SIZE / 4].uint4s[thread_id]:g_dag[*share].uint4s[thread_id]);
}
} while ((a += 4) != (ACCESSES & isolate));
return fnv_reduce(mix);
}
uint inner_loop(uint4 init, uint thread_id, __local uint* share, __global hash128_t const* g_dag, uint isolate)
{
uint4 mix = init;
@ -276,6 +310,7 @@ uint inner_loop(uint4 init, uint thread_id, __local uint* share, __global hash12
return fnv_reduce(mix);
}
hash32_t final_hash(hash64_t const* init, hash32_t const* mix, uint isolate)
{
ulong state[25];
@ -309,7 +344,7 @@ hash32_t compute_hash_simple(
{
mix.uint4s[i] = init.uint4s[i % countof(init.uint4s)];
}
uint mix_val = mix.uints[0];
uint init0 = mix.uints[0];
uint a = 0;
@ -333,7 +368,7 @@ hash32_t compute_hash_simple(
{
fnv_mix.uints[i] = fnv_reduce(mix.uint4s[i]);
}
return final_hash(&init, &fnv_mix, isolate);
}
@ -347,6 +382,7 @@ typedef union
hash32_t mix;
} compute_hash_share;
hash32_t compute_hash(
__local compute_hash_share* share,
__constant hash32_t const* g_header,
@ -390,6 +426,53 @@ hash32_t compute_hash(
return final_hash(&init, &mix, isolate);
}
hash32_t compute_hash_chunks(
__local compute_hash_share* share,
__constant hash32_t const* g_header,
__global hash128_t const* g_dag,
__global hash128_t const* g_dag1,
__global hash128_t const* g_dag2,
__global hash128_t const* g_dag3,
ulong nonce,
uint isolate
)
{
uint const gid = get_global_id(0);
// Compute one init hash per work item.
hash64_t init = init_hash(g_header, nonce, isolate);
// Threads work together in this phase in groups of 8.
uint const thread_id = gid % THREADS_PER_HASH;
uint const hash_id = (gid % GROUP_SIZE) / THREADS_PER_HASH;
hash32_t mix;
uint i = 0;
do
{
// share init with other threads
if (i == thread_id)
share[hash_id].init = init;
barrier(CLK_LOCAL_MEM_FENCE);
uint4 thread_init = share[hash_id].init.uint4s[thread_id % (64 / sizeof(uint4))];
barrier(CLK_LOCAL_MEM_FENCE);
uint thread_mix = inner_loop_chunks(thread_init, thread_id, share[hash_id].mix.uints, g_dag, g_dag1, g_dag2, g_dag3, isolate);
share[hash_id].mix.uints[thread_id] = thread_mix;
barrier(CLK_LOCAL_MEM_FENCE);
if (i == thread_id)
mix = share[hash_id].mix;
barrier(CLK_LOCAL_MEM_FENCE);
}
while (++i != (THREADS_PER_HASH & isolate));
return final_hash(&init, &mix, isolate);
}
__attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1)))
__kernel void ethash_hash_simple(
__global hash32_t* g_hashes,
@ -415,13 +498,15 @@ __kernel void ethash_search_simple(
{
uint const gid = get_global_id(0);
hash32_t hash = compute_hash_simple(g_header, g_dag, start_nonce + gid, isolate);
if (as_ulong(as_uchar8(hash.ulongs[0]).s76543210) < target)
if (hash.ulongs[countof(hash.ulongs)-1] < target)
{
uint slot = min(MAX_OUTPUTS, atomic_inc(&g_output[0]) + 1);
uint slot = min(convert_uint(MAX_OUTPUTS), convert_uint(atomic_inc(&g_output[0]) + 1));
g_output[slot] = gid;
}
}
__attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1)))
__kernel void ethash_hash(
__global hash32_t* g_hashes,
@ -458,3 +543,46 @@ __kernel void ethash_search(
g_output[slot] = gid;
}
}
__attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1)))
__kernel void ethash_hash_chunks(
__global hash32_t* g_hashes,
__constant hash32_t const* g_header,
__global hash128_t const* g_dag,
__global hash128_t const* g_dag1,
__global hash128_t const* g_dag2,
__global hash128_t const* g_dag3,
ulong start_nonce,
uint isolate
)
{
__local compute_hash_share share[HASHES_PER_LOOP];
uint const gid = get_global_id(0);
g_hashes[gid] = compute_hash_chunks(share, g_header, g_dag, g_dag1, g_dag2, g_dag3,start_nonce + gid, isolate);
}
__attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1)))
__kernel void ethash_search_chunks(
__global volatile uint* restrict g_output,
__constant hash32_t const* g_header,
__global hash128_t const* g_dag,
__global hash128_t const* g_dag1,
__global hash128_t const* g_dag2,
__global hash128_t const* g_dag3,
ulong start_nonce,
ulong target,
uint isolate
)
{
__local compute_hash_share share[HASHES_PER_LOOP];
uint const gid = get_global_id(0);
hash32_t hash = compute_hash_chunks(share, g_header, g_dag, g_dag1, g_dag2, g_dag3, start_nonce + gid, isolate);
if (as_ulong(as_uchar8(hash.ulongs[0]).s76543210) < target)
{
uint slot = min(convert_uint(MAX_OUTPUTS), convert_uint(atomic_inc(&g_output[0]) + 1));
g_output[slot] = gid;
}
}

3
libethcore/Ethash.cpp

@ -285,6 +285,7 @@ private:
unsigned Ethash::GPUMiner::s_platformId = 0;
unsigned Ethash::GPUMiner::s_deviceId = 0;
unsigned Ethash::GPUMiner::s_numInstances = 0;
unsigned Ethash::GPUMiner::s_dagChunks = 1;
Ethash::GPUMiner::GPUMiner(ConstructionInfo const& _ci):
Miner(_ci),
@ -345,7 +346,7 @@ void Ethash::GPUMiner::workLoop()
this_thread::sleep_for(chrono::milliseconds(500));
}
bytesConstRef dagData = dag->data();
m_miner->init(dagData.data(), dagData.size(), 32, s_platformId, device);
m_miner->init(dagData.data(), dagData.size(), 32, s_platformId, device, s_dagChunks);
}
uint64_t upper64OfBoundary = (uint64_t)(u64)((u256)w.boundary >> 192);

3
libethcore/Ethash.h

@ -89,6 +89,7 @@ public:
static std::string platformInfo();
static bool haveSufficientGPUMemory() { return false; }
static void setDefaultPlatform(unsigned) {}
static void setDagChunks(unsigned) {}
static void setDefaultDevice(unsigned) {}
static void setNumInstances(unsigned _instances) { s_numInstances = std::min<unsigned>(_instances, std::thread::hardware_concurrency()); }
protected:
@ -121,6 +122,7 @@ public:
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()); }
static void setDagChunks(unsigned _dagChunks) { s_dagChunks = _dagChunks; }
protected:
void kickOff() override;
@ -139,6 +141,7 @@ public:
static unsigned s_platformId;
static unsigned s_deviceId;
static unsigned s_numInstances;
static unsigned s_dagChunks;
};
#else
using GPUMiner = CPUMiner;

23
libethcore/KeyManager.cpp

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

11
libethcore/KeyManager.h

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

3
libethereum/Client.cpp

@ -429,9 +429,10 @@ ExecutionResult Client::call(Address _dest, bytes const& _data, u256 _gas, u256
temp = m_postMine;
temp.addBalance(_from, _value + _gasPrice * _gas);
Executive e(temp, LastHashes(), 0);
e.setResultRecipient(ret);
if (!e.call(_dest, _from, _value, _gasPrice, &_data, _gas))
e.go();
ret = e.executionResult();
e.finalize();
}
catch (...)
{

6
libethereum/CommonNet.h

@ -38,14 +38,16 @@ namespace eth
#if ETH_DEBUG
static const unsigned c_maxHashes = 2048; ///< Maximum number of hashes BlockHashes will ever send.
static const unsigned c_maxHashesAsk = 2048; ///< Maximum number of hashes GetBlockHashes will ever ask for.
static const unsigned c_maxHashesAsk = 256; ///< Maximum number of hashes GetBlockHashes will ever ask for.
static const unsigned c_maxBlocks = 128; ///< Maximum number of blocks Blocks will ever send.
static const unsigned c_maxBlocksAsk = 128; ///< Maximum number of blocks we ask to receive in Blocks (when using GetChain).
static const unsigned c_maxBlocksAsk = 8; ///< Maximum number of blocks we ask to receive in Blocks (when using GetChain).
static const unsigned c_maxPayload = 262144; ///< Maximum size of packet for us to send.
#else
static const unsigned c_maxHashes = 2048; ///< Maximum number of hashes BlockHashes will ever send.
static const unsigned c_maxHashesAsk = 2048; ///< Maximum number of hashes GetBlockHashes will ever ask for.
static const unsigned c_maxBlocks = 128; ///< Maximum number of blocks Blocks will ever send.
static const unsigned c_maxBlocksAsk = 128; ///< Maximum number of blocks we ask to receive in Blocks (when using GetChain).
static const unsigned c_maxPayload = 262144; ///< Maximum size of packet for us to send.
#endif
class BlockChain;

4
libethereum/EthereumHost.cpp

@ -253,7 +253,9 @@ void EthereumHost::onPeerStatus(EthereumPeer* _peer)
if (_peer->m_protocolVersion != protocolVersion())
estimatePeerHashes(_peer);
else if (_peer->m_latestBlockNumber > m_chain.number())
_peer->m_expectedHashes = (unsigned)_peer->m_latestBlockNumber - m_chain.number();
_peer->m_expectedHashes = (unsigned)_peer->m_latestBlockNumber - m_chain.number() + 1000;
else
_peer->m_expectedHashes = 1000;
if (m_hashMan.chainSize() < _peer->m_expectedHashes)
m_hashMan.resetToRange(m_chain.number() + 1, _peer->m_expectedHashes);
continueSync(_peer);

4
libethereum/EthereumPeer.cpp

@ -263,7 +263,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
// return the requested blocks.
bytes rlp;
unsigned n = 0;
for (unsigned i = 0; i < min(count, c_maxBlocks); ++i)
for (unsigned i = 0; i < min(count, c_maxBlocks) && rlp.size() < c_maxPayload; ++i)
{
auto h = _r[i].toHash<h256>();
if (host()->chain().isKnown(h))
@ -286,7 +286,7 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
case BlocksPacket:
{
if (m_asking != Asking::Blocks)
clog(NetWarn) << "Peer giving us blocks when we didn't ask for them.";
clog(NetImpolite) << "Peer giving us blocks when we didn't ask for them.";
else
{
setAsking(Asking::Nothing);

65
libethereum/Executive.cpp

@ -45,11 +45,6 @@ u256 Executive::gasUsed() const
return m_t.gas() - m_gas;
}
ExecutionResult Executive::executionResult() const
{
return ExecutionResult(gasUsed(), m_excepted, m_newAddress, m_out, m_codeDeposit, m_ext ? m_ext->sub.refunds : 0, m_depositSize, m_gasForDeposit);
}
void Executive::accrueSubState(SubState& _parentContext)
{
if (m_ext)
@ -146,8 +141,7 @@ bool Executive::call(CallParameters const& _p, u256 const& _gasPrice, Address co
else
{
m_gas = (u256)(_p.gas - g);
m_precompiledOut = it->second.exec(_p.data);
m_out = &m_precompiledOut;
it->second.exec(_p.data, _p.out);
}
}
else
@ -155,7 +149,7 @@ bool Executive::call(CallParameters const& _p, u256 const& _gasPrice, Address co
m_gas = _p.gas;
if (m_s.addressHasCode(_p.codeAddress))
{
m_vm = VMFactory::create();
m_outRef = _p.out; // Save ref to expected output buffer to be used in go()
bytes const& c = m_s.code(_p.codeAddress);
h256 codeHash = m_s.codeHash(_p.codeAddress);
m_ext = make_shared<ExtVM>(m_s, m_lastHashes, _p.receiveAddress, _p.senderAddress, _origin, _p.value, _gasPrice, _p.data, &c, codeHash, m_depth);
@ -178,10 +172,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g
// Execute _init.
if (!_init.empty())
{
m_vm = VMFactory::create();
m_ext = make_shared<ExtVM>(m_s, m_lastHashes, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, sha3(_init), m_depth);
}
m_s.m_cache[m_newAddress] = Account(m_s.balance(m_newAddress), Account::ContractConception);
m_s.transferBalance(_sender, m_newAddress, _endowment);
@ -232,36 +223,48 @@ OnOpFunc Executive::standardTrace(ostream& o_output)
bool Executive::go(OnOpFunc const& _onOp)
{
if (m_vm)
if (m_ext)
{
#if ETH_TIMED_EXECUTIONS
boost::timer t;
#endif
try
{
m_out = m_vm->go(m_gas, *m_ext, _onOp);
auto vm = VMFactory::create();
if (m_isCreation)
{
m_gasForDeposit = m_gas;
m_depositSize = m_out.size();
if (m_out.size() * c_createDataGas <= m_gas)
auto out = vm->exec(m_gas, *m_ext, _onOp);
if (m_res)
{
m_codeDeposit = CodeDeposit::Success;
m_gas -= m_out.size() * c_createDataGas;
m_res->gasForDeposit = m_gas;
m_res->depositSize = out.size();
}
if (out.size() * c_createDataGas <= m_gas)
{
if (m_res)
m_res->codeDeposit = CodeDeposit::Success;
m_gas -= out.size() * c_createDataGas;
}
else
{
m_codeDeposit = CodeDeposit::Failed;
m_out.reset();
if (m_res)
m_res->codeDeposit = CodeDeposit::Failed;
out.clear();
}
m_s.m_cache[m_newAddress].setCode(m_out.toBytes());
if (m_res)
m_res->output = out; // copy output to execution result
m_s.m_cache[m_newAddress].setCode(std::move(out)); // FIXME: Set only if Success?
}
else
{
if (m_res)
{
m_res->output = vm->exec(m_gas, *m_ext, _onOp); // take full output
bytesConstRef{&m_res->output}.copyTo(m_outRef);
}
else
vm->exec(m_gas, *m_ext, m_outRef, _onOp); // take only expected output
}
}
catch (StepsDone const&)
{
return false;
}
catch (VMException const& _e)
{
@ -315,4 +318,12 @@ void Executive::finalize()
// Logs..
if (m_ext)
m_logs = m_ext->sub.logs;
if (m_res) // Collect results
{
m_res->gasUsed = gasUsed();
m_res->excepted = m_excepted; // TODO: m_except is used only in ExtVM::call
m_res->newAddress = m_newAddress;
m_res->gasRefunded = m_ext ? m_ext->sub.refunds : 0;
}
}

15
libethereum/Executive.h

@ -112,30 +112,25 @@ public:
/// @returns gas remaining after the transaction/operation. Valid after the transaction has been executed.
u256 gas() const { return m_gas; }
/// @returns output data of the transaction/operation.
bytesConstRef out() const { return m_out; }
/// @returns the new address for the created contract in the CREATE operation.
h160 newAddress() const { return m_newAddress; }
/// @returns true iff the operation ended with a VM exception.
bool excepted() const { return m_excepted != TransactionException::None; }
/// Get the above in an amalgamated fashion.
ExecutionResult executionResult() const;
/// Collect execution results in the result storage provided.
void setResultRecipient(ExecutionResult& _res) { m_res = &_res; }
private:
State& m_s; ///< The state to which this operation/transaction is applied.
LastHashes m_lastHashes;
std::shared_ptr<ExtVM> m_ext; ///< The VM externality object for the VM execution or null if no VM is required.
std::unique_ptr<VMFace> m_vm; ///< The VM object or null if no VM is required.
bytes m_precompiledOut; ///< Used for the output when there is no VM for a contract (i.e. precompiled).
bytesConstRef m_out; ///< The copyable output.
bytesRef m_outRef; ///< Reference to "expected output" buffer.
ExecutionResult* m_res = nullptr; ///< Optional storage for execution results.
Address m_newAddress; ///< The address of the created contract in the case of create() being called.
unsigned m_depth = 0; ///< The context's call-depth.
bool m_isCreation = false; ///< True if the transaction creates a contract, or if create() is called.
unsigned m_depositSize = 0; ///< Amount of code of the creation's attempted deposit.
u256 m_gasForDeposit; ///< Amount of gas remaining for the code deposit phase.
CodeDeposit m_codeDeposit = CodeDeposit::None; ///< True if an attempted deposit failed due to lack of gas.
TransactionException m_excepted = TransactionException::None; ///< Details if the VM's execution resulted in an exception.
u256 m_gas = 0; ///< The gas for EVM code execution. Initial amount before go() execution, final amount after go() execution.

1
libethereum/ExtVM.cpp

@ -35,7 +35,6 @@ bool ExtVM::call(CallParameters& _p)
e.accrueSubState(sub);
}
_p.gas = e.gas();
e.out().copyTo(_p.out);
return !e.excepted();
}

55
libethereum/Precompiled.cpp

@ -31,7 +31,10 @@ using namespace std;
using namespace dev;
using namespace dev::eth;
static bytes ecrecoverCode(bytesConstRef _in)
namespace
{
void ecrecoverCode(bytesConstRef _in, bytesRef _out)
{
struct inType
{
@ -44,47 +47,49 @@ static bytes ecrecoverCode(bytesConstRef _in)
memcpy(&in, _in.data(), min(_in.size(), sizeof(in)));
h256 ret;
if ((u256)in.v > 28)
return ret.asBytes();
SignatureStruct sig(in.r, in.s, (byte)((int)(u256)in.v - 27));
if (!sig.isValid())
return ret.asBytes();
try
u256 v = (u256)in.v;
if (v >= 27 && v <= 28)
{
ret = dev::sha3(recover(sig, in.hash));
SignatureStruct sig(in.r, in.s, (byte)((int)v - 27));
if (sig.isValid())
{
try
{
ret = sha3(recover(sig, in.hash));
}
catch (...) {}
}
}
catch (...) {}
memset(ret.data(), 0, 12);
return ret.asBytes();
ret.ref().copyTo(_out);
}
static bytes sha256Code(bytesConstRef _in)
void sha256Code(bytesConstRef _in, bytesRef _out)
{
return sha256(_in).asBytes();
sha256(_in).ref().copyTo(_out);
}
static bytes ripemd160Code(bytesConstRef _in)
void ripemd160Code(bytesConstRef _in, bytesRef _out)
{
return h256(ripemd160(_in), h256::AlignRight).asBytes();
h256(ripemd160(_in), h256::AlignRight).ref().copyTo(_out);
}
static bytes identityCode(bytesConstRef _in)
void identityCode(bytesConstRef _in, bytesRef _out)
{
return _in.toBytes();
_in.copyTo(_out);
}
static const std::unordered_map<unsigned, PrecompiledAddress> c_precompiled =
{
{ 1, { [](bytesConstRef) -> bigint { return c_ecrecoverGas; }, ecrecoverCode }},
{ 2, { [](bytesConstRef i) -> bigint { return c_sha256Gas + (i.size() + 31) / 32 * c_sha256WordGas; }, sha256Code }},
{ 3, { [](bytesConstRef i) -> bigint { return c_ripemd160Gas + (i.size() + 31) / 32 * c_ripemd160WordGas; }, ripemd160Code }},
{ 4, { [](bytesConstRef i) -> bigint { return c_identityGas + (i.size() + 31) / 32 * c_identityWordGas; }, identityCode }}
};
}
std::unordered_map<unsigned, PrecompiledAddress> const& dev::eth::precompiled()
{
static const std::unordered_map<unsigned, PrecompiledAddress> c_precompiled =
{
{ 1, { [](bytesConstRef) -> bigint { return c_ecrecoverGas; }, ecrecoverCode }},
{ 2, { [](bytesConstRef i) -> bigint { return c_sha256Gas + (i.size() + 31) / 32 * c_sha256WordGas; }, sha256Code }},
{ 3, { [](bytesConstRef i) -> bigint { return c_ripemd160Gas + (i.size() + 31) / 32 * c_ripemd160WordGas; }, ripemd160Code }},
{ 4, { [](bytesConstRef i) -> bigint { return c_identityGas + (i.size() + 31) / 32 * c_identityWordGas; }, identityCode }}
};
return c_precompiled;
}

2
libethereum/Precompiled.h

@ -34,7 +34,7 @@ namespace eth
struct PrecompiledAddress
{
std::function<bigint(bytesConstRef)> gas;
std::function<bytes(bytesConstRef)> exec;
std::function<void(bytesConstRef, bytesRef)> exec;
};
/// Info on precompiled contract accounts baked into the protocol.

4
libethereum/State.cpp

@ -1169,6 +1169,8 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per
// Create and initialize the executive. This will throw fairly cheaply and quickly if the
// transaction is bad in any way.
Executive e(*this, _lh, 0);
ExecutionResult res;
e.setResultRecipient(res);
e.initialize(_t);
// Uncommitting is a non-trivial operation - only do it once we've verified as much of the
@ -1228,7 +1230,7 @@ ExecutionResult State::execute(LastHashes const& _lh, Transaction const& _t, Per
m_transactionSet.insert(e.t().sha3());
}
return e.executionResult();
return res;
}
State State::fromPending(unsigned _i) const

17
libethereum/Transaction.h

@ -74,25 +74,14 @@ TransactionException toTransactionException(VMException const& _e);
/// Description of the result of executing a transaction.
struct ExecutionResult
{
ExecutionResult() = default;
ExecutionResult(u256 const& _gasUsed, TransactionException _excepted, Address const& _newAddress, bytesConstRef _output, CodeDeposit _codeDeposit, u256 const& _gasRefund, unsigned _depositSize, u256 const& _gasForDeposit):
gasUsed(_gasUsed),
excepted(_excepted),
newAddress(_newAddress),
output(_output.toBytes()),
codeDeposit(_codeDeposit),
gasRefunded(_gasRefund),
depositSize(_depositSize),
gasForDeposit(_gasForDeposit)
{}
u256 gasUsed = 0;
TransactionException excepted = TransactionException::Unknown;
Address newAddress;
bytes output;
CodeDeposit codeDeposit = CodeDeposit::None;
CodeDeposit codeDeposit = CodeDeposit::None; ///< Failed if an attempted deposit failed due to lack of gas.
u256 gasRefunded = 0;
unsigned depositSize = 0;
u256 gasForDeposit;
unsigned depositSize = 0; ///< Amount of code of the creation's attempted deposit.
u256 gasForDeposit; ///< Amount of gas remaining for the code deposit phase.
};
std::ostream& operator<<(std::ostream& _out, ExecutionResult const& _er);

4
libevm/SmartVM.cpp

@ -41,7 +41,7 @@ namespace
}
}
bytesConstRef SmartVM::go(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
bytesConstRef SmartVM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
{
auto codeHash = sha3(_ext.code);
auto vmKind = VMKind::Interpreter; // default VM
@ -68,7 +68,7 @@ bytesConstRef SmartVM::go(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp,
// TODO: Selected VM must be kept only because it returns reference to its internal memory.
// VM implementations should be stateless, without escaping memory reference.
m_selectedVM = VMFactory::create(vmKind);
return m_selectedVM->go(io_gas, _ext, _onOp, _steps);
return m_selectedVM->execImpl(io_gas, _ext, _onOp);
}
}

2
libevm/SmartVM.h

@ -31,7 +31,7 @@ namespace eth
class SmartVM: public VMFace
{
public:
virtual bytesConstRef go(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final;
virtual bytesConstRef execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp) override final;
private:
std::unique_ptr<VMFace> m_selectedVM;

9
libevm/VM.cpp

@ -45,7 +45,7 @@ static array<InstructionMetric, 256> metrics()
return s_ret;
}
bytesConstRef VM::go(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
bytesConstRef VM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp)
{
// Reset leftovers from possible previous run
m_curPC = 0;
@ -73,8 +73,7 @@ bytesConstRef VM::go(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp, uint6
i += _ext.code[i] - (unsigned)Instruction::PUSH1 + 1;
}
u256 nextPC = m_curPC + 1;
auto osteps = _steps;
for (bool stopped = false; !stopped && _steps--; m_curPC = nextPC, nextPC = m_curPC + 1)
for (uint64_t steps = 0; true; m_curPC = nextPC, nextPC = m_curPC + 1, ++steps)
{
// INSTRUCTION...
Instruction inst = (Instruction)_ext.getCode(m_curPC);
@ -97,7 +96,7 @@ bytesConstRef VM::go(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp, uint6
auto onOperation = [&]()
{
if (_onOp)
_onOp(osteps - _steps - 1, inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, io_gas, this, &_ext);
_onOp(steps, inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, io_gas, this, &_ext);
};
switch (inst)
@ -670,7 +669,5 @@ bytesConstRef VM::go(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp, uint6
}
}
if (_steps == (uint64_t)-1)
BOOST_THROW_EXCEPTION(StepsDone());
return bytesConstRef();
}

2
libevm/VM.h

@ -52,7 +52,7 @@ inline u256 fromAddress(Address _a)
class VM: public VMFace
{
public:
virtual bytesConstRef go(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final;
virtual bytesConstRef execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp) override final;
u256 curPC() const { return m_curPC; }

18
libevm/VMFace.h

@ -26,7 +26,6 @@ namespace eth
{
struct VMException: virtual Exception {};
struct StepsDone: virtual VMException {};
struct BreakPointHit: virtual VMException {};
struct BadInstruction: virtual VMException {};
struct BadJumpDestination: virtual VMException {};
@ -43,7 +42,22 @@ public:
VMFace(VMFace const&) = delete;
VMFace& operator=(VMFace const&) = delete;
virtual bytesConstRef go(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) = 0;
/// Execute EVM code by VM.
///
/// @param _out Expected output
void exec(u256& io_gas, ExtVMFace& _ext, bytesRef _out, OnOpFunc const& _onOp = {})
{
execImpl(io_gas, _ext, _onOp).copyTo(_out);
}
/// The same as above but returns a copy of full output.
bytes exec(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp = {})
{
return execImpl(io_gas, _ext, _onOp).toVector();
}
/// VM implementation
virtual bytesConstRef execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _onOp) = 0;
};
}

4
libevmasm/CommonSubexpressionEliminator.cpp

@ -437,7 +437,7 @@ void CSECodeGenerator::appendDup(int _fromPosition, SourceLocation const& _locat
{
assertThrow(_fromPosition != c_invalidPosition, OptimizerException, "");
int instructionNum = 1 + m_stackHeight - _fromPosition;
assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep.");
assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep, try removing local variables.");
assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access.");
appendItem(AssemblyItem(dupInstruction(instructionNum), _location));
m_stack[m_stackHeight] = m_stack[_fromPosition];
@ -450,7 +450,7 @@ void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation cons
if (_fromPosition == m_stackHeight)
return;
int instructionNum = m_stackHeight - _fromPosition;
assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep.");
assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep, try removing local variables.");
assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access.");
appendItem(AssemblyItem(swapInstruction(instructionNum), _location));

5
libsolidity/ArrayUtils.cpp

@ -168,7 +168,10 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
else
solAssert(false, "Copying of unknown type requested: " + sourceBaseType->toString());
// stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset] <source_value>...
solAssert(2 + byteOffsetSize + sourceBaseType->getSizeOnStack() <= 16, "Stack too deep.");
solAssert(
2 + byteOffsetSize + sourceBaseType->getSizeOnStack() <= 16,
"Stack too deep, try removing local variables."
);
// fetch target storage reference
m_context << eth::dupInstruction(2 + byteOffsetSize + sourceBaseType->getSizeOnStack());
if (haveByteOffsetTarget)

2
libsolidity/Compiler.cpp

@ -367,7 +367,7 @@ bool Compiler::visit(FunctionDefinition const& _function)
stackLayout.push_back(i);
stackLayout += vector<int>(c_localVariablesSize, -1);
solAssert(stackLayout.size() <= 17, "Stack too deep.");
solAssert(stackLayout.size() <= 17, "Stack too deep, try removing local variables.");
while (stackLayout.back() != int(stackLayout.size() - 1))
if (stackLayout.back() < 0)
{

11
libsolidity/CompilerUtils.cpp

@ -142,22 +142,25 @@ void CompilerUtils::moveToStackVariable(VariableDeclaration const& _variable)
solAssert(stackPosition >= size, "Variable size and position mismatch.");
// move variable starting from its top end in the stack
if (stackPosition - size + 1 > 16)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_variable.getLocation())
<< errinfo_comment("Stack too deep."));
BOOST_THROW_EXCEPTION(
CompilerError() <<
errinfo_sourceLocation(_variable.getLocation()) <<
errinfo_comment("Stack too deep, try removing local variables.")
);
for (unsigned i = 0; i < size; ++i)
m_context << eth::swapInstruction(stackPosition - size + 1) << eth::Instruction::POP;
}
void CompilerUtils::copyToStackTop(unsigned _stackDepth, unsigned _itemSize)
{
solAssert(_stackDepth <= 16, "Stack too deep.");
solAssert(_stackDepth <= 16, "Stack too deep, try removing local variables.");
for (unsigned i = 0; i < _itemSize; ++i)
m_context << eth::dupInstruction(_stackDepth);
}
void CompilerUtils::moveToStackTop(unsigned _stackDepth)
{
solAssert(_stackDepth <= 15, "Stack too deep.");
solAssert(_stackDepth <= 15, "Stack too deep, try removing local variables.");
for (unsigned i = 0; i < _stackDepth; ++i)
m_context << eth::swapInstruction(1 + i);
}

2
libsolidity/ExpressionCompiler.cpp

@ -263,7 +263,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
appendOrdinaryBinaryOperatorCode(Token::AssignmentToBinaryOp(op), *_assignment.getType());
if (lvalueSize > 0)
{
solAssert(itemSize + lvalueSize <= 16, "Stack too deep.");
solAssert(itemSize + lvalueSize <= 16, "Stack too deep, try removing local variables.");
// value [lvalue_ref] updated_value
for (unsigned i = 0; i < itemSize; ++i)
m_context << eth::swapInstruction(itemSize + lvalueSize) << eth::Instruction::POP;

26
libsolidity/LValue.cpp

@ -42,8 +42,11 @@ void StackVariable::retrieveValue(SourceLocation const& _location, bool) const
{
unsigned stackPos = m_context.baseToCurrentStackOffset(m_baseStackOffset);
if (stackPos >= 15) //@todo correct this by fetching earlier or moving to memory
BOOST_THROW_EXCEPTION(CompilerError()
<< errinfo_sourceLocation(_location) << errinfo_comment("Stack too deep."));
BOOST_THROW_EXCEPTION(
CompilerError() <<
errinfo_sourceLocation(_location) <<
errinfo_comment("Stack too deep, try removing local variables.")
);
for (unsigned i = 0; i < m_size; ++i)
m_context << eth::dupInstruction(stackPos + 1);
}
@ -52,8 +55,11 @@ void StackVariable::storeValue(Type const&, SourceLocation const& _location, boo
{
unsigned stackDiff = m_context.baseToCurrentStackOffset(m_baseStackOffset) - m_size + 1;
if (stackDiff > 16)
BOOST_THROW_EXCEPTION(CompilerError()
<< errinfo_sourceLocation(_location) << errinfo_comment("Stack too deep."));
BOOST_THROW_EXCEPTION(
CompilerError() <<
errinfo_sourceLocation(_location) <<
errinfo_comment("Stack too deep, try removing local variables.")
);
else if (stackDiff > 0)
for (unsigned i = 0; i < m_size; ++i)
m_context << eth::swapInstruction(stackDiff) << eth::Instruction::POP;
@ -65,8 +71,11 @@ void StackVariable::setToZero(SourceLocation const& _location, bool) const
{
unsigned stackDiff = m_context.baseToCurrentStackOffset(m_baseStackOffset);
if (stackDiff > 16)
BOOST_THROW_EXCEPTION(CompilerError()
<< errinfo_sourceLocation(_location) << errinfo_comment("Stack too deep."));
BOOST_THROW_EXCEPTION(
CompilerError() <<
errinfo_sourceLocation(_location) <<
errinfo_comment("Stack too deep, try removing local variables.")
);
solAssert(stackDiff >= m_size - 1, "");
for (unsigned i = 0; i < m_size; ++i)
m_context << u256(0) << eth::swapInstruction(stackDiff + 1 - i)
@ -204,7 +213,10 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
// stack: source_ref source_off target_ref target_off member_slot_offset member_byte_offset source_member_ref source_member_off
StorageItem(m_context, *memberType).retrieveValue(_location, true);
// stack: source_ref source_off target_ref target_off member_offset source_value...
solAssert(4 + memberType->getSizeOnStack() <= 16, "Stack too deep.");
solAssert(
4 + memberType->getSizeOnStack() <= 16,
"Stack too deep, try removing local varibales."
);
m_context
<< eth::dupInstruction(4 + memberType->getSizeOnStack())
<< eth::dupInstruction(3 + memberType->getSizeOnStack()) << eth::Instruction::ADD

5
mix/MixClient.cpp

@ -130,7 +130,9 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c
State execState = _state;
execState.addBalance(t.sender(), t.gas() * t.gasPrice()); //give it enough balance for gas estimation
eth::ExecutionResult er;
Executive execution(execState, lastHashes, 0);
execution.setResultRecipient(er);
execution.initialize(t);
execution.execute();
std::vector<MachineState> machineStates;
@ -198,7 +200,6 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c
execution.go(onOp);
execution.finalize();
dev::eth::ExecutionResult er = execution.executionResult();
switch (er.excepted)
{
@ -225,7 +226,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c
};
ExecutionResult d;
d.result = execution.executionResult();
d.result = er;
d.machineStates = machineStates;
d.executionCode = std::move(codes);
d.transactionData = std::move(data);

2
solc/CommandLineInterface.cpp

@ -412,8 +412,6 @@ bool CommandLineInterface::processInput()
// TODO: Perhaps we should not compile unless requested
bool optimize = m_args["optimize"].as<bool>();
unsigned runs = m_args["optimize-runs"].as<unsigned>();
if (m_args.count("optimize-runs"))
optimize = true;
m_compiler->compile(optimize, runs);
}
catch (ParserError const& _exception)

4
test/fuzzTesting/checkRandomVMTest.cpp

@ -98,9 +98,9 @@ bool doVMTest(mValue& _v)
try
{
auto vm = eth::VMFactory::create();
output = vm->go(fev.gas, fev, fev.simpleTrace()).toBytes();
output = vm->exec(fev.gas, fev, fev.simpleTrace());
}
catch (eth::VMException)
catch (eth::VMException const&)
{
cnote << "Safe VM Exception";
vmExceptionOccured = true;

2
test/fuzzTesting/createRandomVMTest.cpp

@ -160,7 +160,7 @@ void doMyTests(json_spirit::mValue& _v)
bool vmExceptionOccured = false;
try
{
output = vm->go(fev.gas, fev, fev.simpleTrace()).toBytes();
output = vm->exec(fev.gas, fev, fev.simpleTrace());
}
catch (eth::VMException const& _e)
{

4
test/libevm/vm.cpp

@ -330,12 +330,10 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
{
auto vm = eth::VMFactory::create();
auto vmtrace = Options::get().vmtrace ? fev.simpleTrace() : OnOpFunc{};
auto outputRef = bytesConstRef{};
{
Listener::ExecTimeGuard guard{i.first};
outputRef = vm->go(fev.gas, fev, vmtrace);
output = vm->exec(fev.gas, fev, vmtrace);
}
output = outputRef.toBytes();
}
catch (VMException const&)
{

4
test/libsolidity/solidityExecutionFramework.h

@ -148,6 +148,8 @@ protected:
{
m_state.addBalance(m_sender, _value); // just in case
eth::Executive executive(m_state, eth::LastHashes(), 0);
eth::ExecutionResult res;
executive.setResultRecipient(res);
eth::Transaction t =
_isCreation ?
eth::Transaction(_value, m_gasPrice, m_gas, _data, 0, KeyPair::create().sec()) :
@ -176,7 +178,7 @@ protected:
m_state.noteSending(m_sender);
executive.finalize();
m_gasUsed = executive.gasUsed();
m_output = executive.out().toVector();
m_output = std::move(res.output); // FIXME: Looks like Framework needs ExecutiveResult embedded
m_logs = executive.logs();
}

Loading…
Cancel
Save