diff --git a/alethzero/DappHost.cpp b/alethzero/DappHost.cpp
index fd73c1b17..3b0661ad1 100644
--- a/alethzero/DappHost.cpp
+++ b/alethzero/DappHost.cpp
@@ -28,7 +28,11 @@
using namespace dev;
DappHost::DappHost(int _port, int _threads):
- m_port(_port), m_threads(_threads), m_running(false), m_daemon(nullptr)
+ m_port(_port),
+ m_url(QString("http://localhost:%1/").arg(m_port)),
+ m_threads(_threads),
+ m_running(false),
+ m_daemon(nullptr)
{
startListening();
}
@@ -135,5 +139,10 @@ QUrl DappHost::hostDapp(Dapp&& _dapp)
for (ManifestEntry const& entry: m_dapp.manifest.entries)
m_entriesByPath[QString::fromStdString(entry.path)] = &entry;
- return QUrl(QString("http://localhost:%1/").arg(m_port));
+ return m_url;
+}
+
+bool DappHost::servesUrl(QUrl const& _url) const
+{
+ return m_url == _url || m_url.isParentOf(_url);
}
diff --git a/alethzero/DappHost.h b/alethzero/DappHost.h
index 985bd34d9..50dff741d 100644
--- a/alethzero/DappHost.h
+++ b/alethzero/DappHost.h
@@ -40,6 +40,9 @@ public:
/// Load and host a dapp. Previsous dapp in discarded. Synchronous
QUrl hostDapp(Dapp&& _dapp);
+ /// @returns true if the given url is served from this DappHost.
+ bool servesUrl(QUrl const& _url) const;
+
private:
void startListening();
void stopListening();
@@ -48,7 +51,8 @@ private:
void sendResponse(std::string const& _url, MHD_Connection* _connection);
static int callback(void* _cls, MHD_Connection* _connection, char const* _url, char const* _method, char const* _version, char const* _uploadData, size_t* _uploadDataSize, void** _conCls);
- int m_port;
+ int const m_port;
+ QUrl const m_url;
int m_threads;
bool m_running;
MHD_Daemon* m_daemon;
diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index 60c07fd8d..e48b58283 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -232,6 +232,11 @@ Main::Main(QWidget *parent) :
{
ui->tabWidget->setTabText(0, ui->webView->title());
});
+ connect(ui->webView, &QWebEngineView::urlChanged, [=](QUrl const& _url)
+ {
+ if (!m_dappHost->servesUrl(_url))
+ ui->urlEdit->setText(_url.toString());
+ });
m_dappHost.reset(new DappHost(8081));
m_dappLoader = new DappLoader(this, web3(), getNameReg());
@@ -638,18 +643,22 @@ pair
Main::fromString(std::string const& _n) const
if (_n == "(Create Contract)")
return make_pair(Address(), bytes());
+ std::string n = _n;
+ if (n.find("0x") == 0)
+ n.erase(0, 2);
+
auto g_newNameReg = getNameReg();
if (g_newNameReg)
{
- Address a = abiOut(ethereum()->call(g_newNameReg, abiIn("addr(bytes32)", ::toString32(_n))).output);
+ Address a = abiOut(ethereum()->call(g_newNameReg, abiIn("addr(bytes32)", ::toString32(n))).output);
if (a)
return make_pair(a, bytes());
}
- if (_n.size() == 40)
+ if (n.size() == 40)
{
try
{
- return make_pair(Address(fromHex(_n, WhenError::Throw)), bytes());
+ return make_pair(Address(fromHex(n, WhenError::Throw)), bytes());
}
catch (BadHexCharacter& _e)
{
@@ -665,7 +674,7 @@ pair Main::fromString(std::string const& _n) const
}
else
try {
- return ICAP::decoded(_n).address([&](Address const& a, bytes const& b) -> bytes
+ return ICAP::decoded(n).address([&](Address const& a, bytes const& b) -> bytes
{
return ethereum()->call(a, b).output;
}, g_newNameReg);
diff --git a/eth/main.cpp b/eth/main.cpp
index bd8fbc743..5b38f2779 100644
--- a/eth/main.cpp
+++ b/eth/main.cpp
@@ -910,7 +910,12 @@ void interactiveMode(eth::Client* c, std::shared_ptr gasP
f << endl << " STACK" << endl;
for (auto i: vm->stack())
f << (h256)i << endl;
- f << " MEMORY" << endl << dev::memDump(vm->memory());
+ std::string memDump = (
+ (vm->memory().size() > 1000) ?
+ " mem size greater than 1000 bytes " :
+ dev::memDump(vm->memory())
+ );
+ f << " MEMORY" << endl << memDump;
f << " STORAGE" << endl;
for (auto const& i: ext->state().storage(ext->myAddress))
f << showbase << hex << i.first << ": " << i.second << endl;
diff --git a/extdep/getstuff.bat b/extdep/getstuff.bat
index 3c0b42f95..a718650b7 100644
--- a/extdep/getstuff.bat
+++ b/extdep/getstuff.bat
@@ -11,6 +11,7 @@ call :download curl 7.4.2
call :download jsoncpp 1.6.2
call :download json-rpc-cpp 0.5.0
call :download leveldb 1.2
+call :download llvm 3.7svn
call :download microhttpd 0.9.2
call :download qt 5.4.1
call :download miniupnpc 1.9
diff --git a/libethash-cl/ethash_cl_miner.cpp b/libethash-cl/ethash_cl_miner.cpp
index 50fb273b6..f5fcacb75 100644
--- a/libethash-cl/ethash_cl_miner.cpp
+++ b/libethash-cl/ethash_cl_miner.cpp
@@ -327,6 +327,8 @@ bool ethash_cl_miner::init(
m_globalWorkSize = ((m_globalWorkSize / s_workgroupSize) + 1) * s_workgroupSize;
// remember the device's address bits
m_deviceBits = device.getInfo();
+ // make sure first step of global work size adjustment is large enough
+ m_stepWorkSizeAdjust = pow(2, m_deviceBits / 2 + 1);
// patch source code
// note: ETHASH_CL_MINER_KERNEL is simply ethash_cl_miner_kernel.cl compiled
@@ -532,14 +534,26 @@ void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook
{
if (d > chrono::milliseconds(s_msPerBatch * 10 / 9))
{
- // cerr << "Batch of " << m_globalWorkSize << " took " << chrono::duration_cast(d).count() << " ms, >> " << _msPerBatch << " ms." << endl;
- m_globalWorkSize = max(128, m_globalWorkSize + s_workgroupSize);
+ // Divide the step by 2 when adjustment way change
+ if (m_wayWorkSizeAdjust > -1)
+ m_stepWorkSizeAdjust = max(1, m_stepWorkSizeAdjust / 2);
+ m_wayWorkSizeAdjust = -1;
+ // cerr << "m_stepWorkSizeAdjust: " << m_stepWorkSizeAdjust << ", m_wayWorkSizeAdjust: " << m_wayWorkSizeAdjust << endl;
+
+ // cerr << "Batch of " << m_globalWorkSize << " took " << chrono::duration_cast(d).count() << " ms, >> " << s_msPerBatch << " ms." << endl;
+ m_globalWorkSize = max(128, m_globalWorkSize - m_stepWorkSizeAdjust);
// cerr << "New global work size" << m_globalWorkSize << endl;
}
else if (d < chrono::milliseconds(s_msPerBatch * 9 / 10))
{
- // cerr << "Batch of " << m_globalWorkSize << " took " << chrono::duration_cast(d).count() << " ms, << " << _msPerBatch << " ms." << endl;
- m_globalWorkSize = min(pow(2, m_deviceBits) - 1, m_globalWorkSize - s_workgroupSize);
+ // Divide the step by 2 when adjustment way change
+ if (m_wayWorkSizeAdjust < 1)
+ m_stepWorkSizeAdjust = max(1, m_stepWorkSizeAdjust / 2);
+ m_wayWorkSizeAdjust = 1;
+ // cerr << "m_stepWorkSizeAdjust: " << m_stepWorkSizeAdjust << ", m_wayWorkSizeAdjust: " << m_wayWorkSizeAdjust << endl;
+
+ // cerr << "Batch of " << m_globalWorkSize << " took " << chrono::duration_cast(d).count() << " ms, << " << s_msPerBatch << " ms." << endl;
+ m_globalWorkSize = min(pow(2, m_deviceBits) - 1, m_globalWorkSize + m_stepWorkSizeAdjust);
// Global work size should never be less than the workgroup size
m_globalWorkSize = max(s_workgroupSize, m_globalWorkSize);
// cerr << "New global work size" << m_globalWorkSize << endl;
diff --git a/libethash-cl/ethash_cl_miner.h b/libethash-cl/ethash_cl_miner.h
index 3ea2fba4a..c51c38fb6 100644
--- a/libethash-cl/ethash_cl_miner.h
+++ b/libethash-cl/ethash_cl_miner.h
@@ -90,6 +90,11 @@ private:
bool m_openclOnePointOne;
unsigned m_deviceBits;
+ /// The step used in the work size adjustment
+ unsigned int m_stepWorkSizeAdjust;
+ /// The Work Size way of adjustment, > 0 when previously increased, < 0 when previously decreased
+ int m_wayWorkSizeAdjust = 0;
+
/// The local work size for the search
static unsigned s_workgroupSize;
/// The initial global work size for the searches
diff --git a/libethcore/KeyManager.cpp b/libethcore/KeyManager.cpp
index 602c60b4a..26cf451d0 100644
--- a/libethcore/KeyManager.cpp
+++ b/libethcore/KeyManager.cpp
@@ -213,6 +213,7 @@ void KeyManager::kill(Address const& _a)
m_addrLookup.erase(_a);
m_keyInfo.erase(id);
m_store.kill(id);
+ write(m_keysFile);
}
Addresses KeyManager::accounts() const
diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp
index d9a54a1ee..768ed223f 100644
--- a/libethereum/BlockChain.cpp
+++ b/libethereum/BlockChain.cpp
@@ -597,9 +597,19 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const&
// Most of the time these two will be equal - only when we're doing a chain revert will they not be
if (common != last)
+ {
+ // Erase the number-lookup cache for the segment of the chain that we're reverting (if any).
+ unsigned n = number(route.front());
+ DEV_WRITE_GUARDED(x_blockHashes)
+ for (auto i = route.begin(); i != route.end() && *i != common; ++i, --n)
+ m_blockHashes.erase(h256(u256(n)));
+ DEV_WRITE_GUARDED(x_transactionAddresses)
+ m_transactionAddresses.clear(); // TODO: could perhaps delete them individually?
+
// If we are reverting previous blocks, we need to clear their blooms (in particular, to
// rebuild any higher level blooms that they contributed to).
clearBlockBlooms(number(common) + 1, number(last) + 1);
+ }
// Go through ret backwards until hash != last.parent and update m_transactionAddresses, m_blockHashes
for (auto i = route.rbegin(); i != route.rend() && *i != common; ++i)
@@ -630,7 +640,7 @@ ImportRoute BlockChain::import(VerifiedBlockRef const& _block, OverlayDB const&
}
}
// Collate transaction hashes and remember who they were.
- h256s newTransactionAddresses;
+ //h256s newTransactionAddresses;
{
bytes blockBytes;
RLP blockRLP(*i == _block.info.hash() ? _block.block : &(blockBytes = block(*i)));
diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp
index 161a7d35a..0cca63a80 100644
--- a/libsolidity/AST.cpp
+++ b/libsolidity/AST.cpp
@@ -426,7 +426,14 @@ void InheritanceSpecifier::checkTypeRequirements()
solAssert(base, "Base contract not available.");
TypePointers parameterTypes = ContractType(*base).getConstructorType()->getParameterTypes();
if (!m_arguments.empty() && parameterTypes.size() != m_arguments.size())
- BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for constructor call."));
+ BOOST_THROW_EXCEPTION(createTypeError(
+ "Wrong argument count for constructor call: " +
+ toString(m_arguments.size()) +
+ " arguments given but expected " +
+ toString(parameterTypes.size()) +
+ "."
+ ));
+
for (size_t i = 0; i < m_arguments.size(); ++i)
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i]))
BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError(
@@ -629,7 +636,13 @@ void ModifierInvocation::checkTypeRequirements(vector
if (!parameters)
BOOST_THROW_EXCEPTION(createTypeError("Referenced declaration is neither modifier nor base class."));
if (parameters->size() != m_arguments.size())
- BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for modifier invocation."));
+ BOOST_THROW_EXCEPTION(createTypeError(
+ "Wrong argument count for modifier invocation: " +
+ toString(m_arguments.size()) +
+ " arguments given but expected " +
+ toString(parameters->size()) +
+ "."
+ ));
for (size_t i = 0; i < m_arguments.size(); ++i)
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*(*parameters)[i]->getType()))
BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError(
@@ -834,7 +847,13 @@ void FunctionCall::checkTypeRequirements(TypePointers const*)
// function parameters
TypePointers const& parameterTypes = functionType->getParameterTypes();
if (!functionType->takesArbitraryParameters() && parameterTypes.size() != m_arguments.size())
- BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call."));
+ BOOST_THROW_EXCEPTION(createTypeError(
+ "Wrong argument count for function call: " +
+ toString(m_arguments.size()) +
+ " arguments given but expected " +
+ toString(parameterTypes.size()) +
+ "."
+ ));
if (isPositionalCall)
{
diff --git a/libsolidity/ArrayUtils.cpp b/libsolidity/ArrayUtils.cpp
index f13b28173..48ee5a052 100644
--- a/libsolidity/ArrayUtils.cpp
+++ b/libsolidity/ArrayUtils.cpp
@@ -37,7 +37,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
// this copies source to target and also clears target if it was larger
// need to leave "target_ref target_byte_off" on the stack at the end
- // stack layout: [source_ref] [source_byte_off] [source length] target_ref target_byte_off (top)
+ // stack layout: [source_ref] [source length] target_ref (top)
solAssert(_targetType.location() == DataLocation::Storage, "");
IntegerType uint256(256);
@@ -53,16 +53,11 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
bool haveByteOffsetTarget = !directCopy && targetBaseType->getStorageBytes() <= 16;
unsigned byteOffsetSize = (haveByteOffsetSource ? 1 : 0) + (haveByteOffsetTarget ? 1 : 0);
- // stack: source_ref [source_byte_off] [source_length] target_ref target_byte_off
+ // stack: source_ref [source_length] target_ref
// store target_ref
- // arrays always start at zero byte offset, pop offset
- m_context << eth::Instruction::POP;
for (unsigned i = _sourceType.getSizeOnStack(); i > 0; --i)
m_context << eth::swapInstruction(i);
- // stack: target_ref source_ref [source_byte_off] [source_length]
- if (sourceIsStorage)
- // arrays always start at zero byte offset, pop offset
- m_context << eth::Instruction::POP;
+ // stack: target_ref source_ref [source_length]
// stack: target_ref source_ref [source_length]
// retrieve source length
if (_sourceType.location() != DataLocation::CallData || !_sourceType.isDynamicallySized())
@@ -90,7 +85,6 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
m_context
<< eth::Instruction::POP << eth::Instruction::POP
<< eth::Instruction::POP << eth::Instruction::POP;
- m_context << u256(0);
return;
}
// compute hashes (data positions)
@@ -136,13 +130,11 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
solAssert(byteOffsetSize == 0, "Byte offset for array as base type.");
auto const& sourceBaseArrayType = dynamic_cast(*sourceBaseType);
m_context << eth::Instruction::DUP3;
- if (sourceIsStorage)
- m_context << u256(0);
- else if (sourceBaseArrayType.location() == DataLocation::Memory)
+ if (sourceBaseArrayType.location() == DataLocation::Memory)
m_context << eth::Instruction::MLOAD;
- m_context << eth::dupInstruction(sourceIsStorage ? 4 : 3) << u256(0);
+ m_context << eth::Instruction::DUP3;
copyArrayToStorage(dynamic_cast(*targetBaseType), sourceBaseArrayType);
- m_context << eth::Instruction::POP << eth::Instruction::POP;
+ m_context << eth::Instruction::POP;
}
else if (directCopy)
{
@@ -235,7 +227,6 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
// stack: target_ref target_data_end target_data_pos_updated
clearStorageLoop(*targetBaseType);
m_context << eth::Instruction::POP;
- m_context << u256(0);
}
void ArrayUtils::copyArrayToMemory(const ArrayType& _sourceType, bool _padToWordBoundaries) const
@@ -365,7 +356,6 @@ void ArrayUtils::copyArrayToMemory(const ArrayType& _sourceType, bool _padToWord
u256 storageSize = _sourceType.getBaseType()->getStorageSize();
solAssert(storageSize > 1 || (storageSize == 1 && storageBytes > 0), "");
- m_context << eth::Instruction::POP; // remove offset, arrays always start new slot
retrieveLength(_sourceType);
// stack here: memory_offset storage_offset length
// jump to end if length is zero
diff --git a/libsolidity/ArrayUtils.h b/libsolidity/ArrayUtils.h
index c047fdcc0..80ffc008a 100644
--- a/libsolidity/ArrayUtils.h
+++ b/libsolidity/ArrayUtils.h
@@ -41,8 +41,8 @@ public:
/// Copies an array to an array in storage. The arrays can be of different types only if
/// their storage representation is the same.
- /// Stack pre: source_reference [source_byte_offset/source_length] target_reference target_byte_offset
- /// Stack post: target_reference target_byte_offset
+ /// Stack pre: source_reference [source_length] target_reference
+ /// Stack post: target_reference
void copyArrayToStorage(ArrayType const& _targetType, ArrayType const& _sourceType) const;
/// Copies the data part of an array (which cannot be dynamically nested) from anywhere
/// to a given position in memory.
diff --git a/libsolidity/CompilerUtils.cpp b/libsolidity/CompilerUtils.cpp
index 297e6aa09..e62f59e23 100644
--- a/libsolidity/CompilerUtils.cpp
+++ b/libsolidity/CompilerUtils.cpp
@@ -229,7 +229,7 @@ void CompilerUtils::encodeToMemory(
if (arrayType.location() == DataLocation::CallData)
m_context << eth::Instruction::DUP2; // length is on stack
else if (arrayType.location() == DataLocation::Storage)
- m_context << eth::Instruction::DUP3 << eth::Instruction::SLOAD;
+ m_context << eth::Instruction::DUP2 << eth::Instruction::SLOAD;
else
{
solAssert(arrayType.location() == DataLocation::Memory, "");
@@ -416,13 +416,6 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
{
// stack: