From 4ef4f7658f090580e7bc6910969aacfe67506ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 23 Jul 2015 15:56:54 +0200 Subject: [PATCH 01/41] Fix empty EVM code in SmartVM. --- libevm/SmartVM.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libevm/SmartVM.cpp b/libevm/SmartVM.cpp index 50a548002..abbe4fddf 100644 --- a/libevm/SmartVM.cpp +++ b/libevm/SmartVM.cpp @@ -54,7 +54,7 @@ namespace bool isStopSentinel() { - assert((!code.empty() || !codeHash) && "'empty code => empty hash' invariand failed"); + assert((!code.empty() || !codeHash) && "'empty code => empty hash' invariant failed"); return code.empty(); } }; @@ -102,7 +102,7 @@ bytesConstRef SmartVM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _ clog(JitInfo) << "JIT: " << codeHash; vmKind = VMKind::JIT; } - else + else if (!_ext.code.empty()) // This check is needed for VM tests { static JitWorker s_worker; From 947b9e9664d768c9bf84658524cff78ec1a0cc83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 23 Jul 2015 16:24:15 +0200 Subject: [PATCH 02/41] Replace "bad jump" exit with "abort" exit. --- evmjit/include/evmjit/JIT-c.h | 1 - evmjit/include/evmjit/JIT.h | 1 - evmjit/libevmjit-cpp/JitVM.cpp | 2 -- evmjit/libevmjit/Compiler.cpp | 30 +++++------------------------- evmjit/libevmjit/Compiler.h | 7 +------ 5 files changed, 6 insertions(+), 35 deletions(-) diff --git a/evmjit/include/evmjit/JIT-c.h b/evmjit/include/evmjit/JIT-c.h index a92b29090..c7b91b48a 100644 --- a/evmjit/include/evmjit/JIT-c.h +++ b/evmjit/include/evmjit/JIT-c.h @@ -40,7 +40,6 @@ typedef enum evmjit_return_code // Standard error codes OutOfGas = -1, StackUnderflow = -2, - BadJumpDestination = -3, BadInstruction = -4, Rejected = -5, ///< Input data (code, gas, block info, etc.) does not meet JIT requirement and execution request has been rejected diff --git a/evmjit/include/evmjit/JIT.h b/evmjit/include/evmjit/JIT.h index e74534243..91b088dc3 100644 --- a/evmjit/include/evmjit/JIT.h +++ b/evmjit/include/evmjit/JIT.h @@ -102,7 +102,6 @@ enum class ReturnCode // Standard error codes OutOfGas = -1, StackUnderflow = -2, - BadJumpDestination = -3, BadInstruction = -4, Rejected = -5, ///< Input data (code, gas, block info, etc.) does not meet JIT requirement and execution request has been rejected diff --git a/evmjit/libevmjit-cpp/JitVM.cpp b/evmjit/libevmjit-cpp/JitVM.cpp index d96da87c1..43565f8bf 100644 --- a/evmjit/libevmjit-cpp/JitVM.cpp +++ b/evmjit/libevmjit-cpp/JitVM.cpp @@ -60,8 +60,6 @@ bytesConstRef JitVM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _on _ext.suicide(right160(jit2eth(m_data.address))); break; - case evmjit::ReturnCode::BadJumpDestination: - BOOST_THROW_EXCEPTION(BadJumpDestination()); case evmjit::ReturnCode::OutOfGas: BOOST_THROW_EXCEPTION(OutOfGas()); case evmjit::ReturnCode::StackUnderflow: // FIXME: Remove support for detail errors diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index a44e4e890..16a842c89 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -94,7 +94,7 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn } } -llvm::BasicBlock* Compiler::getJumpTableBlock(RuntimeManager& _runtimeManager) +llvm::BasicBlock* Compiler::getJumpTableBlock() { if (!m_jumpTableBlock) { @@ -102,7 +102,7 @@ llvm::BasicBlock* Compiler::getJumpTableBlock(RuntimeManager& _runtimeManager) InsertPointGuard g{m_builder}; m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); auto dest = m_builder.CreatePHI(Type::Word, 8, "target"); - auto switchInstr = m_builder.CreateSwitch(dest, getBadJumpBlock(_runtimeManager)); + auto switchInstr = m_builder.CreateSwitch(dest, m_abortBB); for (auto&& p : m_basicBlocks) { if (p.second.isJumpDest()) @@ -112,18 +112,6 @@ llvm::BasicBlock* Compiler::getJumpTableBlock(RuntimeManager& _runtimeManager) return m_jumpTableBlock->llvm(); } -llvm::BasicBlock* Compiler::getBadJumpBlock(RuntimeManager& _runtimeManager) -{ - if (!m_badJumpBlock) - { - m_badJumpBlock.reset(new BasicBlock("BadJump", m_mainFunc, m_builder, true)); - InsertPointGuard g{m_builder}; - m_builder.SetInsertPoint(m_badJumpBlock->llvm()); - _runtimeManager.exit(ReturnCode::BadJumpDestination); - } - return m_badJumpBlock->llvm(); -} - std::unique_ptr Compiler::compile(code_iterator _begin, code_iterator _end, std::string const& _id) { auto module = std::unique_ptr(new llvm::Module(_id, m_builder.getContext())); @@ -616,7 +604,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti auto&& c = constant->getValue(); auto targetIdx = c.getActiveBits() <= 64 ? c.getZExtValue() : -1; auto it = m_basicBlocks.find(targetIdx); - targetBlock = (it != m_basicBlocks.end() && it->second.isJumpDest()) ? it->second.llvm() : getBadJumpBlock(_runtimeManager); + targetBlock = (it != m_basicBlocks.end() && it->second.isJumpDest()) ? it->second.llvm() : m_abortBB; } // TODO: Improve; check for constants @@ -629,7 +617,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti else { _basicBlock.setJumpTarget(target); - m_builder.CreateBr(getJumpTableBlock(_runtimeManager)); + m_builder.CreateBr(getJumpTableBlock()); } } else // JUMPI @@ -645,7 +633,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti else { _basicBlock.setJumpTarget(target); - m_builder.CreateCondBr(cond, getJumpTableBlock(_runtimeManager), _nextBasicBlock); + m_builder.CreateCondBr(cond, getJumpTableBlock(), _nextBasicBlock); } } break; @@ -901,12 +889,6 @@ void Compiler::removeDeadBlocks() m_jumpTableBlock->llvm()->eraseFromParent(); m_jumpTableBlock.reset(); } - - if (m_badJumpBlock && llvm::pred_begin(m_badJumpBlock->llvm()) == llvm::pred_end(m_badJumpBlock->llvm())) - { - m_badJumpBlock->llvm()->eraseFromParent(); - m_badJumpBlock.reset(); - } } void Compiler::dumpCFGifRequired(std::string const& _dotfilePath) @@ -931,8 +913,6 @@ void Compiler::dumpCFGtoStream(std::ostream& _out) blocks.push_back(&pair.second); if (m_jumpTableBlock) blocks.push_back(m_jumpTableBlock.get()); - if (m_badJumpBlock) - blocks.push_back(m_badJumpBlock.get()); // std::map phiNodesPerBlock; diff --git a/evmjit/libevmjit/Compiler.h b/evmjit/libevmjit/Compiler.h index 0b31ae0f2..7c90fbceb 100644 --- a/evmjit/libevmjit/Compiler.h +++ b/evmjit/libevmjit/Compiler.h @@ -37,9 +37,7 @@ private: void compileBasicBlock(BasicBlock& _basicBlock, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock); - llvm::BasicBlock* getJumpTableBlock(RuntimeManager& _runtimeManager); - - llvm::BasicBlock* getBadJumpBlock(RuntimeManager& _runtimeManager); + llvm::BasicBlock* getJumpTableBlock(); void removeDeadBlocks(); @@ -70,9 +68,6 @@ private: /// Block with a jump table. std::unique_ptr m_jumpTableBlock; - /// Destination for invalid jumps - std::unique_ptr m_badJumpBlock; - /// Main program function llvm::Function* m_mainFunc = nullptr; }; From 0e3629387af93976a9bcc8c5eed999238b555b05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 23 Jul 2015 16:29:40 +0200 Subject: [PATCH 03/41] Remove unused return codes. --- evmjit/include/evmjit/JIT-c.h | 3 --- evmjit/include/evmjit/JIT.h | 3 --- evmjit/libevmjit-cpp/JitVM.cpp | 4 ---- 3 files changed, 10 deletions(-) diff --git a/evmjit/include/evmjit/JIT-c.h b/evmjit/include/evmjit/JIT-c.h index c7b91b48a..98e8ade33 100644 --- a/evmjit/include/evmjit/JIT-c.h +++ b/evmjit/include/evmjit/JIT-c.h @@ -39,9 +39,6 @@ typedef enum evmjit_return_code // Standard error codes OutOfGas = -1, - StackUnderflow = -2, - BadInstruction = -4, - Rejected = -5, ///< Input data (code, gas, block info, etc.) does not meet JIT requirement and execution request has been rejected // Internal error codes LLVMError = -101, diff --git a/evmjit/include/evmjit/JIT.h b/evmjit/include/evmjit/JIT.h index 91b088dc3..285a33218 100644 --- a/evmjit/include/evmjit/JIT.h +++ b/evmjit/include/evmjit/JIT.h @@ -101,9 +101,6 @@ enum class ReturnCode // Standard error codes OutOfGas = -1, - StackUnderflow = -2, - BadInstruction = -4, - Rejected = -5, ///< Input data (code, gas, block info, etc.) does not meet JIT requirement and execution request has been rejected // Internal error codes LLVMError = -101, diff --git a/evmjit/libevmjit-cpp/JitVM.cpp b/evmjit/libevmjit-cpp/JitVM.cpp index 43565f8bf..d05632955 100644 --- a/evmjit/libevmjit-cpp/JitVM.cpp +++ b/evmjit/libevmjit-cpp/JitVM.cpp @@ -62,10 +62,6 @@ bytesConstRef JitVM::execImpl(u256& io_gas, ExtVMFace& _ext, OnOpFunc const& _on case evmjit::ReturnCode::OutOfGas: BOOST_THROW_EXCEPTION(OutOfGas()); - case evmjit::ReturnCode::StackUnderflow: // FIXME: Remove support for detail errors - BOOST_THROW_EXCEPTION(StackUnderflow()); - case evmjit::ReturnCode::BadInstruction: - BOOST_THROW_EXCEPTION(BadInstruction()); case evmjit::ReturnCode::LinkerWorkaround: // never happens env_sload(); // but forces linker to include env_* JIT callback functions break; From c80ded8f9793216a27f9b40d95e197447ae8169d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 24 Jul 2015 15:01:58 +0200 Subject: [PATCH 04/41] Move LocalStack out of BasicBlock. --- evmjit/libevmjit/BasicBlock.cpp | 22 +++++------ evmjit/libevmjit/BasicBlock.h | 67 ++++++++++++++++----------------- evmjit/libevmjit/Compiler.cpp | 8 ++-- evmjit/libevmjit/Compiler.h | 2 +- 4 files changed, 47 insertions(+), 52 deletions(-) diff --git a/evmjit/libevmjit/BasicBlock.cpp b/evmjit/libevmjit/BasicBlock.cpp index a41743d0b..b40296f40 100644 --- a/evmjit/libevmjit/BasicBlock.cpp +++ b/evmjit/libevmjit/BasicBlock.cpp @@ -28,23 +28,22 @@ BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iter m_begin(_begin), m_end(_end), m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {isJumpDest ? jumpDestName : basicBlockName, std::to_string(_firstInstrIdx)}, _mainFunc)), - m_stack(*this), m_builder(_builder), m_isJumpDest(isJumpDest) {} BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest) : m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)), - m_stack(*this), m_builder(_builder), m_isJumpDest(isJumpDest) {} -BasicBlock::LocalStack::LocalStack(BasicBlock& _owner) : - m_bblock(_owner) +LocalStack::LocalStack(BasicBlock& _owner, Stack& _globalStack) : + m_bblock(_owner), + m_global(_globalStack) {} -void BasicBlock::LocalStack::push(llvm::Value* _value) +void LocalStack::push(llvm::Value* _value) { assert(_value->getType() == Type::Word); m_bblock.m_currentStack.push_back(_value); @@ -52,7 +51,7 @@ void BasicBlock::LocalStack::push(llvm::Value* _value) m_maxSize = std::max(m_maxSize, m_bblock.m_currentStack.size()); } -llvm::Value* BasicBlock::LocalStack::pop() +llvm::Value* LocalStack::pop() { auto result = get(0); @@ -66,7 +65,7 @@ llvm::Value* BasicBlock::LocalStack::pop() /** * Pushes a copy of _index-th element (tos is 0-th elem). */ -void BasicBlock::LocalStack::dup(size_t _index) +void LocalStack::dup(size_t _index) { auto val = get(_index); push(val); @@ -76,7 +75,7 @@ void BasicBlock::LocalStack::dup(size_t _index) * Swaps tos with _index-th element (tos is 0-th elem). * _index must be > 0. */ -void BasicBlock::LocalStack::swap(size_t _index) +void LocalStack::swap(size_t _index) { assert(_index > 0); auto val = get(_index); @@ -85,7 +84,7 @@ void BasicBlock::LocalStack::swap(size_t _index) set(0, val); } -std::vector::iterator BasicBlock::LocalStack::getItemIterator(size_t _index) +std::vector::iterator LocalStack::getItemIterator(size_t _index) { auto& currentStack = m_bblock.m_currentStack; if (_index < currentStack.size()) @@ -98,7 +97,7 @@ std::vector::iterator BasicBlock::LocalStack::getItemIterator(size return currentStack.end() - _index - 1; } -llvm::Value* BasicBlock::LocalStack::get(size_t _index) +llvm::Value* LocalStack::get(size_t _index) { auto& initialStack = m_bblock.m_initialStack; auto itemIter = getItemIterator(_index); @@ -124,7 +123,7 @@ llvm::Value* BasicBlock::LocalStack::get(size_t _index) return *itemIter; } -void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word) +void LocalStack::set(size_t _index, llvm::Value* _word) { auto itemIter = getItemIterator(_index); *itemIter = _word; @@ -388,4 +387,3 @@ void BasicBlock::dump(std::ostream& _out, bool _dotOutput) } } } - diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index 321499196..cbac2b048 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -14,47 +14,48 @@ namespace jit using namespace evmjit; using instr_idx = uint64_t; -class BasicBlock +class BasicBlock; + +class LocalStack { public: - class LocalStack - { - public: - /// Pushes value on stack - void push(llvm::Value* _value); + LocalStack(BasicBlock& _owner, Stack& _globalStack); + LocalStack(LocalStack const&) = delete; + void operator=(LocalStack const&) = delete; - /// Pops and returns top value - llvm::Value* pop(); + /// Pushes value on stack + void push(llvm::Value* _value); - /// Duplicates _index'th value on stack - void dup(size_t _index); + /// Pops and returns top value + llvm::Value* pop(); - /// Swaps _index'th value on stack with a value on stack top. - /// @param _index Index of value to be swaped. Must be > 0. - void swap(size_t _index); + /// Duplicates _index'th value on stack + void dup(size_t _index); - size_t getMaxSize() const { return m_maxSize; } - int getDiff() const { return m_bblock.m_tosOffset; } + /// Swaps _index'th value on stack with a value on stack top. + /// @param _index Index of value to be swaped. Must be > 0. + void swap(size_t _index); - private: - LocalStack(BasicBlock& _owner); - LocalStack(LocalStack const&) = delete; - void operator=(LocalStack const&) = delete; - friend BasicBlock; + size_t getMaxSize() const { return m_maxSize; } - /// Gets _index'th value from top (counting from 0) - llvm::Value* get(size_t _index); +private: + /// Gets _index'th value from top (counting from 0) + llvm::Value* get(size_t _index); - /// Sets _index'th value from top (counting from 0) - void set(size_t _index, llvm::Value* _value); + /// Sets _index'th value from top (counting from 0) + void set(size_t _index, llvm::Value* _value); - std::vector::iterator getItemIterator(size_t _index); + std::vector::iterator getItemIterator(size_t _index); - private: - BasicBlock& m_bblock; - size_t m_maxSize = 0; ///< Max size reached by the stack. - }; +private: + BasicBlock& m_bblock; + Stack& m_global; + size_t m_maxSize = 0; ///< Max size reached by the stack. +}; +class BasicBlock +{ +public: explicit BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest); explicit BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest); @@ -72,7 +73,7 @@ public: llvm::Value* getJumpTarget() const { return m_jumpTarget; } void setJumpTarget(llvm::Value* _jumpTarget) { m_jumpTarget = _jumpTarget; } - LocalStack& localStack() { return m_stack; } + int getDiff() const { return m_tosOffset; } /// Optimization: propagates values between local stacks in basic blocks /// to avoid excessive pushing/popping on the EVM stack. @@ -93,10 +94,6 @@ private: llvm::BasicBlock* const m_llvmBB; - /// Basic black state vector (stack) - current/end values and their positions on stack - /// @internal Must be AFTER m_llvmBB - LocalStack m_stack; - llvm::IRBuilder<>& m_builder; /// This stack contains LLVM values that correspond to items found at @@ -111,6 +108,7 @@ private: /// executes. It may grow on both sides, as the code pushes items on /// top of the stack or changes existing items. std::vector m_currentStack; + friend class LocalStack; /// How many items higher is the current stack than the initial one. /// May be negative. @@ -127,4 +125,3 @@ private: } } } - diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 16a842c89..73fc3c0d9 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -163,7 +163,7 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera auto iterCopy = basicBlockPairIt; ++iterCopy; auto nextBasicBlock = (iterCopy != m_basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; - compileBasicBlock(basicBlock, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock); + compileBasicBlock(basicBlock, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock, stack); } // Code for special blocks: @@ -224,13 +224,13 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runtimeManager, - Arith256& _arith, Memory& _memory, Ext& _ext, GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock) + Arith256& _arith, Memory& _memory, Ext& _ext, GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock, Stack& _globalStack) { if (!_nextBasicBlock) // this is the last block in the code _nextBasicBlock = m_stopBB; m_builder.SetInsertPoint(_basicBlock.llvm()); - auto& stack = _basicBlock.localStack(); + LocalStack stack{_basicBlock, _globalStack}; for (auto it = _basicBlock.begin(); it != _basicBlock.end(); ++it) { @@ -857,7 +857,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti m_builder.CreateBr(_nextBasicBlock); m_builder.SetInsertPoint(_basicBlock.llvm()->getFirstNonPHI()); - _runtimeManager.checkStackLimit(_basicBlock.localStack().getMaxSize(), _basicBlock.localStack().getDiff()); + _runtimeManager.checkStackLimit(stack.getMaxSize(), _basicBlock.getDiff()); } diff --git a/evmjit/libevmjit/Compiler.h b/evmjit/libevmjit/Compiler.h index 7c90fbceb..e606044e8 100644 --- a/evmjit/libevmjit/Compiler.h +++ b/evmjit/libevmjit/Compiler.h @@ -35,7 +35,7 @@ private: void createBasicBlocks(code_iterator _begin, code_iterator _end); - void compileBasicBlock(BasicBlock& _basicBlock, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock); + void compileBasicBlock(BasicBlock& _basicBlock, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock, class Stack& _globalStack); llvm::BasicBlock* getJumpTableBlock(); From b604dfefe6d0078f5d3786dd7971642753cad156 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Jul 2015 11:55:49 +0200 Subject: [PATCH 05/41] Reimplementation of local stack handling during basic block compilation. This change removed the intermediate stage when PHI nodes are inserted in place of items fetched from global stack. PHi stage requires information about other basic block therefore must be postponed to the point when all basic blocks has been compiled. In the same time this optimization has not been very effective. --- evmjit/libevmjit/BasicBlock.cpp | 119 +++++++++++--------------------- evmjit/libevmjit/BasicBlock.h | 4 +- evmjit/libevmjit/Compiler.h | 3 +- 3 files changed, 45 insertions(+), 81 deletions(-) diff --git a/evmjit/libevmjit/BasicBlock.cpp b/evmjit/libevmjit/BasicBlock.cpp index b40296f40..bb2673d9c 100644 --- a/evmjit/libevmjit/BasicBlock.cpp +++ b/evmjit/libevmjit/BasicBlock.cpp @@ -53,13 +53,16 @@ void LocalStack::push(llvm::Value* _value) llvm::Value* LocalStack::pop() { - auto result = get(0); + auto item = get(0); + assert(!m_bblock.m_currentStack.empty() || !m_bblock.m_initialStack.empty()); if (m_bblock.m_currentStack.size() > 0) m_bblock.m_currentStack.pop_back(); + else + ++m_bblock.m_globalPops; m_bblock.m_tosOffset -= 1; - return result; + return item; } /** @@ -84,109 +87,71 @@ void LocalStack::swap(size_t _index) set(0, val); } -std::vector::iterator LocalStack::getItemIterator(size_t _index) +llvm::Value* LocalStack::get(size_t _index) { auto& currentStack = m_bblock.m_currentStack; if (_index < currentStack.size()) - return currentStack.end() - _index - 1; + return *(currentStack.rbegin() + _index); // count from back - // Need to map more elements from the EVM stack - auto nNewItems = 1 + _index - currentStack.size(); - currentStack.insert(currentStack.begin(), nNewItems, nullptr); - - return currentStack.end() - _index - 1; -} - -llvm::Value* LocalStack::get(size_t _index) -{ auto& initialStack = m_bblock.m_initialStack; - auto itemIter = getItemIterator(_index); + auto idx = _index - currentStack.size() + m_bblock.m_globalPops; + if (idx >= initialStack.size()) + initialStack.resize(idx + 1); + auto& item = initialStack[idx]; - if (*itemIter == nullptr) - { - // Need to fetch a new item from the EVM stack - assert(static_cast(_index) >= m_bblock.m_tosOffset); - size_t initialIdx = _index - m_bblock.m_tosOffset; - if (initialIdx >= initialStack.size()) - { - auto nNewItems = 1 + initialIdx - initialStack.size(); - initialStack.insert(initialStack.end(), nNewItems, nullptr); - } + if (!item) + item = m_global.get(idx); - assert(initialStack[initialIdx] == nullptr); - // Create a dummy value. - std::string name = "get_" + std::to_string(_index); - initialStack[initialIdx] = m_bblock.m_builder.CreatePHI(Type::Word, 0, std::move(name)); - *itemIter = initialStack[initialIdx]; - } - - return *itemIter; + return item; } void LocalStack::set(size_t _index, llvm::Value* _word) { - auto itemIter = getItemIterator(_index); - *itemIter = _word; -} - - + auto& currentStack = m_bblock.m_currentStack; + if (_index < currentStack.size()) + { + *(currentStack.rbegin() + _index) = _word; + return; + } + auto& initialStack = m_bblock.m_initialStack; + auto idx = _index - currentStack.size() + m_bblock.m_globalPops; + assert(idx < initialStack.size()); + initialStack[idx] = _word; +} void BasicBlock::synchronizeLocalStack(Stack& _evmStack) { auto blockTerminator = m_llvmBB->getTerminator(); - assert(blockTerminator != nullptr); + assert(blockTerminator); if (blockTerminator->getOpcode() != llvm::Instruction::Ret) { - // Not needed in case of ret instruction. Ret also invalidates the stack. + // Not needed in case of ret instruction. Ret invalidates the stack. m_builder.SetInsertPoint(blockTerminator); - auto currIter = m_currentStack.begin(); - auto endIter = m_currentStack.end(); - - // Update (emit set()) changed values - for (int idx = (int)m_currentStack.size() - 1 - m_tosOffset; - currIter < endIter && idx >= 0; - ++currIter, --idx) + // Update items fetched from global stack ignoring the poped ones + assert(m_globalPops <= m_initialStack.size()); // pop() always does get() + for (auto i = m_globalPops; i < m_initialStack.size(); ++i) { - assert(static_cast(idx) < m_initialStack.size()); - if (*currIter != m_initialStack[idx]) // value needs update - _evmStack.set(static_cast(idx), *currIter); + if (m_initialStack[i]) + _evmStack.set(i, m_initialStack[i]); } - // Pop values - if (m_tosOffset < 0) - _evmStack.pop(static_cast(-m_tosOffset)); - - // Push new values - for (; currIter < endIter; ++currIter) + // Add new items + for (auto& item: m_currentStack) { - assert(*currIter != nullptr); - _evmStack.push(*currIter); + if (m_globalPops) // Override poped global items + _evmStack.set(--m_globalPops, item); // using pops counter as the index + else + _evmStack.push(item); } - } - // Emit get() for all (used) values from the initial stack - for (size_t idx = 0; idx < m_initialStack.size(); ++idx) - { - auto val = m_initialStack[idx]; - if (val == nullptr) - continue; - - llvm::PHINode* phi = llvm::cast(val); - // Insert call to get() just before the PHI node and replace - // the uses of PHI with the uses of this new instruction. - m_builder.SetInsertPoint(phi); - auto newVal = _evmStack.get(idx); // OPT: Value may be never user but we need to check stack heigth - // It is probably a good idea to keep heigth as a local variable accesible by LLVM directly - phi->replaceAllUsesWith(newVal); - phi->eraseFromParent(); + // Pop not overriden items + if (m_globalPops) + _evmStack.pop(m_globalPops); } - // Reset the stack - m_initialStack.erase(m_initialStack.begin(), m_initialStack.end()); - m_currentStack.erase(m_currentStack.begin(), m_currentStack.end()); m_tosOffset = 0; } @@ -211,8 +176,6 @@ void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRB it != initialStack.end() && *it != nullptr; ++it, ++inputItems); - //if (bblock.localStack().m_tosOffset > 0) - // outputItems = bblock.localStack().m_tosOffset; auto& exitStack = bblock.m_currentStack; for (auto it = exitStack.rbegin(); it != exitStack.rend() && *it != nullptr; diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index cbac2b048..7a20d4104 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -45,8 +45,6 @@ private: /// Sets _index'th value from top (counting from 0) void set(size_t _index, llvm::Value* _value); - std::vector::iterator getItemIterator(size_t _index); - private: BasicBlock& m_bblock; Stack& m_global; @@ -114,6 +112,8 @@ private: /// May be negative. int m_tosOffset = 0; + size_t m_globalPops = 0; ///< Number of items poped from global stack. In other words: global - local stack overlap. + /// Is the basic block a valid jump destination. /// JUMPDEST is the first instruction of the basic block. bool const m_isJumpDest = false; diff --git a/evmjit/libevmjit/Compiler.h b/evmjit/libevmjit/Compiler.h index e606044e8..b6b3c3c2d 100644 --- a/evmjit/libevmjit/Compiler.h +++ b/evmjit/libevmjit/Compiler.h @@ -16,7 +16,8 @@ public: struct Options { /// Optimize stack operations between basic blocks - bool optimizeStack = true; + /// TODO: Remove. It must be implemented as a separated pass. + bool optimizeStack = false; /// Rewrite switch instructions to sequences of branches bool rewriteSwitchToBranches = true; From fcacf6e3a2681bf94f4d571925e493e75ad0ce70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Jul 2015 12:20:12 +0200 Subject: [PATCH 06/41] Remove code doing stack optimization with PHI nodes. --- evmjit/libevmjit/BasicBlock.cpp | 145 +--------------------------- evmjit/libevmjit/BasicBlock.h | 10 +- evmjit/libevmjit/Compiler.cpp | 14 --- evmjit/libevmjit/Compiler.h | 4 - evmjit/libevmjit/RuntimeManager.cpp | 2 +- evmjit/libevmjit/RuntimeManager.h | 2 +- 6 files changed, 4 insertions(+), 173 deletions(-) diff --git a/evmjit/libevmjit/BasicBlock.cpp b/evmjit/libevmjit/BasicBlock.cpp index bb2673d9c..83ef3c7eb 100644 --- a/evmjit/libevmjit/BasicBlock.cpp +++ b/evmjit/libevmjit/BasicBlock.cpp @@ -47,7 +47,6 @@ void LocalStack::push(llvm::Value* _value) { assert(_value->getType() == Type::Word); m_bblock.m_currentStack.push_back(_value); - m_bblock.m_tosOffset += 1; m_maxSize = std::max(m_maxSize, m_bblock.m_currentStack.size()); } @@ -61,7 +60,6 @@ llvm::Value* LocalStack::pop() else ++m_bblock.m_globalPops; - m_bblock.m_tosOffset -= 1; return item; } @@ -151,147 +149,6 @@ void BasicBlock::synchronizeLocalStack(Stack& _evmStack) if (m_globalPops) _evmStack.pop(m_globalPops); } - - m_tosOffset = 0; -} - -void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRBuilder<>& _builder) -{ - struct BBInfo - { - BasicBlock& bblock; - std::vector predecessors; - size_t inputItems; - size_t outputItems; - std::vector phisToRewrite; - - BBInfo(BasicBlock& _bblock) : - bblock(_bblock), - predecessors(), - inputItems(0), - outputItems(0) - { - auto& initialStack = bblock.m_initialStack; - for (auto it = initialStack.begin(); - it != initialStack.end() && *it != nullptr; - ++it, ++inputItems); - - auto& exitStack = bblock.m_currentStack; - for (auto it = exitStack.rbegin(); - it != exitStack.rend() && *it != nullptr; - ++it, ++outputItems); - } - }; - - std::map cfg; - - // Create nodes in cfg - for (auto bb : basicBlocks) - cfg.emplace(bb->llvm(), *bb); - - // Create edges in cfg: for each bb info fill the list - // of predecessor infos. - for (auto& pair : cfg) - { - auto bb = pair.first; - auto& info = pair.second; - - for (auto predIt = llvm::pred_begin(bb); predIt != llvm::pred_end(bb); ++predIt) - { - auto predInfoEntry = cfg.find(*predIt); - if (predInfoEntry != cfg.end()) // FIXME: It is wrong - will skip entry block - info.predecessors.push_back(&predInfoEntry->second); - } - } - - // Iteratively compute inputs and outputs of each block, until reaching fixpoint. - bool valuesChanged = true; - while (valuesChanged) - { - for (auto& pair : cfg) - { - DLOG(bb) << pair.second.bblock.llvm()->getName().str() - << ": in " << pair.second.inputItems - << ", out " << pair.second.outputItems - << "\n"; - } - - valuesChanged = false; - for (auto& pair : cfg) - { - auto& info = pair.second; - - if (&info.bblock == basicBlocks.front()) - info.inputItems = 0; // we cannot use phi nodes for first block as it is a successor of entry block - - if (info.predecessors.empty()) - info.inputItems = 0; // no consequences for other blocks, so leave valuesChanged false - - for (auto predInfo : info.predecessors) - { - if (predInfo->outputItems < info.inputItems) - { - info.inputItems = predInfo->outputItems; - valuesChanged = true; - } - else if (predInfo->outputItems > info.inputItems) - { - predInfo->outputItems = info.inputItems; - valuesChanged = true; - } - } - } - } - - // Propagate values between blocks. - for (auto& entry : cfg) - { - auto& info = entry.second; - auto& bblock = info.bblock; - - llvm::BasicBlock::iterator fstNonPhi(bblock.llvm()->getFirstNonPHI()); - auto phiIter = bblock.m_initialStack.begin(); - for (size_t index = 0; index < info.inputItems; ++index, ++phiIter) - { - assert(llvm::isa(*phiIter)); - auto phi = llvm::cast(*phiIter); - - for (auto predIt : info.predecessors) - { - auto& predExitStack = predIt->bblock.m_currentStack; - auto value = *(predExitStack.end() - 1 - index); - phi->addIncoming(value, predIt->bblock.llvm()); - } - - // Move phi to the front - if (llvm::BasicBlock::iterator(phi) != bblock.llvm()->begin()) - { - phi->removeFromParent(); - _builder.SetInsertPoint(bblock.llvm(), bblock.llvm()->begin()); - _builder.Insert(phi); - } - } - - // The items pulled directly from predecessors block must be removed - // from the list of items that has to be popped from the initial stack. - auto& initialStack = bblock.m_initialStack; - initialStack.erase(initialStack.begin(), initialStack.begin() + info.inputItems); - // Initial stack shrinks, so the size difference grows: - bblock.m_tosOffset += (int)info.inputItems; - } - - // We must account for the items that were pushed directly to successor - // blocks and thus should not be on the list of items to be pushed onto - // to EVM stack - for (auto& entry : cfg) - { - auto& info = entry.second; - auto& bblock = info.bblock; - - auto& exitStack = bblock.m_currentStack; - exitStack.erase(exitStack.end() - info.outputItems, exitStack.end()); - bblock.m_tosOffset -= (int)info.outputItems; // FIXME: Fix types - } } void BasicBlock::dump() @@ -323,7 +180,7 @@ void BasicBlock::dump(std::ostream& _out, bool _dotOutput) out << *ins << (_dotOutput ? "\\l" : "\n"); if (! _dotOutput) - out << "Current stack (offset = " << m_tosOffset << "):\n"; + out << "Current stack:\n"; else out << "|"; diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index 7a20d4104..3111eb942 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -71,11 +71,7 @@ public: llvm::Value* getJumpTarget() const { return m_jumpTarget; } void setJumpTarget(llvm::Value* _jumpTarget) { m_jumpTarget = _jumpTarget; } - int getDiff() const { return m_tosOffset; } - - /// Optimization: propagates values between local stacks in basic blocks - /// to avoid excessive pushing/popping on the EVM stack. - static void linkLocalStacks(std::vector _basicBlocks, llvm::IRBuilder<>& _builder); + ssize_t getDiff() const { return static_cast(m_currentStack.size()) - static_cast(m_globalPops); } /// Synchronize current local stack with the EVM stack. void synchronizeLocalStack(Stack& _evmStack); @@ -108,10 +104,6 @@ private: std::vector m_currentStack; friend class LocalStack; - /// How many items higher is the current stack than the initial one. - /// May be negative. - int m_tosOffset = 0; - size_t m_globalPops = 0; ///< Number of items poped from global stack. In other words: global - local stack overlap. /// Is the basic block a valid jump destination. diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 73fc3c0d9..05d5a0fd1 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -198,20 +198,6 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera dumpCFGifRequired("blocks-init.dot"); - if (m_options.optimizeStack) - { - std::vector blockList; - for (auto& entry : m_basicBlocks) - blockList.push_back(&entry.second); - - if (m_jumpTableBlock) - blockList.push_back(m_jumpTableBlock.get()); - - BasicBlock::linkLocalStacks(blockList, m_builder); - - dumpCFGifRequired("blocks-opt.dot"); - } - for (auto& entry : m_basicBlocks) entry.second.synchronizeLocalStack(stack); if (m_jumpTableBlock) diff --git a/evmjit/libevmjit/Compiler.h b/evmjit/libevmjit/Compiler.h index b6b3c3c2d..b9a9aae9b 100644 --- a/evmjit/libevmjit/Compiler.h +++ b/evmjit/libevmjit/Compiler.h @@ -15,10 +15,6 @@ public: struct Options { - /// Optimize stack operations between basic blocks - /// TODO: Remove. It must be implemented as a separated pass. - bool optimizeStack = false; - /// Rewrite switch instructions to sequences of branches bool rewriteSwitchToBranches = true; diff --git a/evmjit/libevmjit/RuntimeManager.cpp b/evmjit/libevmjit/RuntimeManager.cpp index 971f14abd..b55d90a1a 100644 --- a/evmjit/libevmjit/RuntimeManager.cpp +++ b/evmjit/libevmjit/RuntimeManager.cpp @@ -145,7 +145,7 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB m_builder.CreateUnreachable(); } -void RuntimeManager::checkStackLimit(size_t _max, int _diff) +void RuntimeManager::checkStackLimit(size_t _max, ssize_t _diff) { createCall(m_checkStackLimit, {m_stackSize, m_builder.getInt64(_max), m_builder.getInt64(_diff), getJmpBuf()}); } diff --git a/evmjit/libevmjit/RuntimeManager.h b/evmjit/libevmjit/RuntimeManager.h index 8c0728aaf..aa8f4838b 100644 --- a/evmjit/libevmjit/RuntimeManager.h +++ b/evmjit/libevmjit/RuntimeManager.h @@ -50,7 +50,7 @@ public: static llvm::StructType* getRuntimeType(); static llvm::StructType* getRuntimeDataType(); - void checkStackLimit(size_t _max, int _diff); + void checkStackLimit(size_t _max, ssize_t _diff); private: llvm::Value* getPtr(RuntimeData::Index _index); From 1e926fe6bc5b82c53d23a0797dcf037e0c64052d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Jul 2015 13:57:48 +0200 Subject: [PATCH 07/41] Move fields from BasicBlock to LocalStack. Remove dump() functions. --- evmjit/libevmjit/BasicBlock.cpp | 115 ++++++++------------------------ evmjit/libevmjit/BasicBlock.h | 55 ++++++--------- evmjit/libevmjit/Compiler.cpp | 82 ++--------------------- evmjit/libevmjit/Compiler.h | 9 --- 4 files changed, 57 insertions(+), 204 deletions(-) diff --git a/evmjit/libevmjit/BasicBlock.cpp b/evmjit/libevmjit/BasicBlock.cpp index 83ef3c7eb..f4f8b4645 100644 --- a/evmjit/libevmjit/BasicBlock.cpp +++ b/evmjit/libevmjit/BasicBlock.cpp @@ -23,42 +23,39 @@ namespace jit static const char* jumpDestName = "JmpDst."; static const char* basicBlockName = "Instr."; -BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest) : +BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, bool isJumpDest): m_firstInstrIdx{_firstInstrIdx}, m_begin(_begin), m_end(_end), m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {isJumpDest ? jumpDestName : basicBlockName, std::to_string(_firstInstrIdx)}, _mainFunc)), - m_builder(_builder), m_isJumpDest(isJumpDest) {} -BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest) : +BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, bool isJumpDest): m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)), - m_builder(_builder), m_isJumpDest(isJumpDest) {} -LocalStack::LocalStack(BasicBlock& _owner, Stack& _globalStack) : - m_bblock(_owner), +LocalStack::LocalStack(Stack& _globalStack): m_global(_globalStack) {} void LocalStack::push(llvm::Value* _value) { assert(_value->getType() == Type::Word); - m_bblock.m_currentStack.push_back(_value); - m_maxSize = std::max(m_maxSize, m_bblock.m_currentStack.size()); + m_currentStack.push_back(_value); + m_maxSize = std::max(m_maxSize, m_currentStack.size()); // FIXME: This is wrong too. + add min size; } llvm::Value* LocalStack::pop() { auto item = get(0); - assert(!m_bblock.m_currentStack.empty() || !m_bblock.m_initialStack.empty()); + assert(!m_currentStack.empty() || !m_initialStack.empty()); - if (m_bblock.m_currentStack.size() > 0) - m_bblock.m_currentStack.pop_back(); + if (m_currentStack.size() > 0) + m_currentStack.pop_back(); else - ++m_bblock.m_globalPops; + ++m_globalPops; return item; } @@ -87,15 +84,13 @@ void LocalStack::swap(size_t _index) llvm::Value* LocalStack::get(size_t _index) { - auto& currentStack = m_bblock.m_currentStack; - if (_index < currentStack.size()) - return *(currentStack.rbegin() + _index); // count from back + if (_index < m_currentStack.size()) + return *(m_currentStack.rbegin() + _index); // count from back - auto& initialStack = m_bblock.m_initialStack; - auto idx = _index - currentStack.size() + m_bblock.m_globalPops; - if (idx >= initialStack.size()) - initialStack.resize(idx + 1); - auto& item = initialStack[idx]; + auto idx = _index - m_currentStack.size() + m_globalPops; + if (idx >= m_initialStack.size()) + m_initialStack.resize(idx + 1); + auto& item = m_initialStack[idx]; if (!item) item = m_global.get(idx); @@ -105,104 +100,50 @@ llvm::Value* LocalStack::get(size_t _index) void LocalStack::set(size_t _index, llvm::Value* _word) { - auto& currentStack = m_bblock.m_currentStack; - if (_index < currentStack.size()) + if (_index < m_currentStack.size()) { - *(currentStack.rbegin() + _index) = _word; + *(m_currentStack.rbegin() + _index) = _word; return; } - auto& initialStack = m_bblock.m_initialStack; - auto idx = _index - currentStack.size() + m_bblock.m_globalPops; - assert(idx < initialStack.size()); - initialStack[idx] = _word; + auto idx = _index - m_currentStack.size() + m_globalPops; + assert(idx < m_initialStack.size()); + m_initialStack[idx] = _word; } -void BasicBlock::synchronizeLocalStack(Stack& _evmStack) +void LocalStack::finalize(llvm::IRBuilder<>& _builder, llvm::BasicBlock& _bb) { - auto blockTerminator = m_llvmBB->getTerminator(); + auto blockTerminator = _bb.getTerminator(); assert(blockTerminator); if (blockTerminator->getOpcode() != llvm::Instruction::Ret) { // Not needed in case of ret instruction. Ret invalidates the stack. - m_builder.SetInsertPoint(blockTerminator); + _builder.SetInsertPoint(blockTerminator); // Update items fetched from global stack ignoring the poped ones assert(m_globalPops <= m_initialStack.size()); // pop() always does get() for (auto i = m_globalPops; i < m_initialStack.size(); ++i) { if (m_initialStack[i]) - _evmStack.set(i, m_initialStack[i]); + m_global.set(i, m_initialStack[i]); } // Add new items for (auto& item: m_currentStack) { - if (m_globalPops) // Override poped global items - _evmStack.set(--m_globalPops, item); // using pops counter as the index + if (m_globalPops) // Override poped global items + m_global.set(--m_globalPops, item); // using pops counter as the index else - _evmStack.push(item); + m_global.push(item); } // Pop not overriden items if (m_globalPops) - _evmStack.pop(m_globalPops); + m_global.pop(m_globalPops); } } -void BasicBlock::dump() -{ - dump(std::cerr, false); -} - -void BasicBlock::dump(std::ostream& _out, bool _dotOutput) -{ - llvm::raw_os_ostream out(_out); - - out << (_dotOutput ? "" : "Initial stack:\n"); - for (auto val : m_initialStack) - { - if (val == nullptr) - out << " ?"; - else if (llvm::isa(val)) - out << " " << val->getName(); - else if (llvm::isa(val)) - out << *val; - else - out << " " << *val; - - out << (_dotOutput ? "\\l" : "\n"); - } - - out << (_dotOutput ? "| " : "Instructions:\n"); - for (auto ins = m_llvmBB->begin(); ins != m_llvmBB->end(); ++ins) - out << *ins << (_dotOutput ? "\\l" : "\n"); - - if (! _dotOutput) - out << "Current stack:\n"; - else - out << "|"; - - for (auto val = m_currentStack.rbegin(); val != m_currentStack.rend(); ++val) - { - if (*val == nullptr) - out << " ?"; - else if (llvm::isa(*val)) - out << " " << (*val)->getName(); - else if (llvm::isa(*val)) - out << **val; - else - out << " " << **val; - out << (_dotOutput ? "\\l" : "\n"); - } - - if (! _dotOutput) - out << " ...\n----------------------------------------\n"; -} - - - } } diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index 3111eb942..75b0efeab 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -19,7 +19,7 @@ class BasicBlock; class LocalStack { public: - LocalStack(BasicBlock& _owner, Stack& _globalStack); + explicit LocalStack(Stack& _globalStack); LocalStack(LocalStack const&) = delete; void operator=(LocalStack const&) = delete; @@ -36,8 +36,13 @@ public: /// @param _index Index of value to be swaped. Must be > 0. void swap(size_t _index); + ssize_t getDiff() const { return static_cast(m_currentStack.size()) - static_cast(m_globalPops); } size_t getMaxSize() const { return m_maxSize; } + /// TODO: comment + /// TODO: It must be the same builder as in global stack. + void finalize(llvm::IRBuilder<>& _builder, llvm::BasicBlock& _bb); + private: /// Gets _index'th value from top (counting from 0) llvm::Value* get(size_t _index); @@ -45,8 +50,20 @@ private: /// Sets _index'th value from top (counting from 0) void set(size_t _index, llvm::Value* _value); -private: - BasicBlock& m_bblock; + /// This stack contains LLVM values that correspond to items found at + /// the EVM stack when the current basic block starts executing. + /// Location 0 corresponds to the top of the EVM stack, location 1 is + /// the item below the top and so on. The stack grows as the code + /// accesses more items on the EVM stack but once a value is put on + /// the stack, it will never be replaced. + std::vector m_initialStack; + + /// This stack tracks the contents of the EVM stack as the basic block + /// executes. It may grow on both sides, as the code pushes items on + /// top of the stack or changes existing items. + std::vector m_currentStack; + + size_t m_globalPops = 0; ///< Number of items poped from global stack. In other words: global - local stack overlap. Stack& m_global; size_t m_maxSize = 0; ///< Max size reached by the stack. }; @@ -54,8 +71,8 @@ private: class BasicBlock { public: - explicit BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest); - explicit BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest); + explicit BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, bool isJumpDest); + explicit BasicBlock(std::string _name, llvm::Function* _mainFunc, bool isJumpDest); BasicBlock(const BasicBlock&) = delete; BasicBlock& operator=(const BasicBlock&) = delete; @@ -71,16 +88,6 @@ public: llvm::Value* getJumpTarget() const { return m_jumpTarget; } void setJumpTarget(llvm::Value* _jumpTarget) { m_jumpTarget = _jumpTarget; } - ssize_t getDiff() const { return static_cast(m_currentStack.size()) - static_cast(m_globalPops); } - - /// Synchronize current local stack with the EVM stack. - void synchronizeLocalStack(Stack& _evmStack); - - /// Prints local stack and block instructions to stderr. - /// Useful for calling in a debugger session. - void dump(); - void dump(std::ostream& os, bool _dotOutput = false); - private: instr_idx const m_firstInstrIdx = 0; ///< Code index of first instruction in the block code_iterator const m_begin = {}; ///< Iterator pointing code beginning of the block @@ -88,24 +95,6 @@ private: llvm::BasicBlock* const m_llvmBB; - llvm::IRBuilder<>& m_builder; - - /// This stack contains LLVM values that correspond to items found at - /// the EVM stack when the current basic block starts executing. - /// Location 0 corresponds to the top of the EVM stack, location 1 is - /// the item below the top and so on. The stack grows as the code - /// accesses more items on the EVM stack but once a value is put on - /// the stack, it will never be replaced. - std::vector m_initialStack; - - /// This stack tracks the contents of the EVM stack as the basic block - /// executes. It may grow on both sides, as the code pushes items on - /// top of the stack or changes existing items. - std::vector m_currentStack; - friend class LocalStack; - - size_t m_globalPops = 0; ///< Number of items poped from global stack. In other words: global - local stack overlap. - /// Is the basic block a valid jump destination. /// JUMPDEST is the first instruction of the basic block. bool const m_isJumpDest = false; diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 05d5a0fd1..58d8809d3 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -87,7 +87,7 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn { auto beginIdx = begin - _codeBegin; m_basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginIdx), - std::forward_as_tuple(beginIdx, begin, next, m_mainFunc, m_builder, nextJumpDest)); + std::forward_as_tuple(beginIdx, begin, next, m_mainFunc, nextJumpDest)); nextJumpDest = false; begin = next; } @@ -98,12 +98,12 @@ llvm::BasicBlock* Compiler::getJumpTableBlock() { if (!m_jumpTableBlock) { - m_jumpTableBlock.reset(new BasicBlock("JumpTable", m_mainFunc, m_builder, true)); + m_jumpTableBlock.reset(new BasicBlock("JumpTable", m_mainFunc, true)); InsertPointGuard g{m_builder}; m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); auto dest = m_builder.CreatePHI(Type::Word, 8, "target"); auto switchInstr = m_builder.CreateSwitch(dest, m_abortBB); - for (auto&& p : m_basicBlocks) + for (auto&& p : m_basicBlocks) // FIXME: It mast be done at the end { if (p.second.isJumpDest()) switchInstr->addCase(Constant::get(p.first), p.second.llvm()); @@ -196,15 +196,6 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera } } - dumpCFGifRequired("blocks-init.dot"); - - for (auto& entry : m_basicBlocks) - entry.second.synchronizeLocalStack(stack); - if (m_jumpTableBlock) - m_jumpTableBlock->synchronizeLocalStack(stack); - - dumpCFGifRequired("blocks-sync.dot"); - return module; } @@ -216,7 +207,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti _nextBasicBlock = m_stopBB; m_builder.SetInsertPoint(_basicBlock.llvm()); - LocalStack stack{_basicBlock, _globalStack}; + LocalStack stack{_globalStack}; for (auto it = _basicBlock.begin(); it != _basicBlock.end(); ++it) { @@ -842,12 +833,13 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti if (!_basicBlock.llvm()->getTerminator()) m_builder.CreateBr(_nextBasicBlock); + stack.finalize(m_builder, *_basicBlock.llvm()); // TODO: Use references + m_builder.SetInsertPoint(_basicBlock.llvm()->getFirstNonPHI()); - _runtimeManager.checkStackLimit(stack.getMaxSize(), _basicBlock.getDiff()); + _runtimeManager.checkStackLimit(stack.getMaxSize(), stack.getDiff()); } - void Compiler::removeDeadBlocks() { // Remove dead basic blocks @@ -877,66 +869,6 @@ void Compiler::removeDeadBlocks() } } -void Compiler::dumpCFGifRequired(std::string const& _dotfilePath) -{ - if (! m_options.dumpCFG) - return; - - // TODO: handle i/o failures - std::ofstream ofs(_dotfilePath); - dumpCFGtoStream(ofs); - ofs.close(); -} - -void Compiler::dumpCFGtoStream(std::ostream& _out) -{ - _out << "digraph BB {\n" - << " node [shape=record, fontname=Courier, fontsize=10];\n" - << " entry [share=record, label=\"entry block\"];\n"; - - std::vector blocks; - for (auto& pair : m_basicBlocks) - blocks.push_back(&pair.second); - if (m_jumpTableBlock) - blocks.push_back(m_jumpTableBlock.get()); - - // std::map phiNodesPerBlock; - - // Output nodes - for (auto bb : blocks) - { - std::string blockName = bb->llvm()->getName(); - - std::ostringstream oss; - bb->dump(oss, true); - - _out << " \"" << blockName << "\" [shape=record, label=\" { " << blockName << "|" << oss.str() << "} \"];\n"; - } - - // Output edges - for (auto bb : blocks) - { - std::string blockName = bb->llvm()->getName(); - - auto end = llvm::pred_end(bb->llvm()); - for (llvm::pred_iterator it = llvm::pred_begin(bb->llvm()); it != end; ++it) - { - _out << " \"" << (*it)->getName().str() << "\" -> \"" << blockName << "\" [" - << ((m_jumpTableBlock.get() && *it == m_jumpTableBlock.get()->llvm()) ? "style = dashed, " : "") - << "];\n"; - } - } - - _out << "}\n"; -} - -void Compiler::dump() -{ - for (auto& entry : m_basicBlocks) - entry.second.dump(); - if (m_jumpTableBlock != nullptr) - m_jumpTableBlock->dump(); -} } } diff --git a/evmjit/libevmjit/Compiler.h b/evmjit/libevmjit/Compiler.h index b9a9aae9b..a8cfa30e7 100644 --- a/evmjit/libevmjit/Compiler.h +++ b/evmjit/libevmjit/Compiler.h @@ -38,15 +38,6 @@ private: void removeDeadBlocks(); - /// Dumps basic block graph in graphviz format to a file, if option dumpCFG is enabled. - void dumpCFGifRequired(std::string const& _dotfilePath); - - /// Dumps basic block graph in graphviz format to a stream. - void dumpCFGtoStream(std::ostream& _out); - - /// Dumps all basic blocks to stderr. Useful in a debugging session. - void dump(); - /// Compiler options Options const& m_options; From 3ffdcd9f1399eff22bb71ff2df930b951d86e12f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Jul 2015 14:25:28 +0200 Subject: [PATCH 08/41] Test dynamic jumps. --- evmjit/libevmjit/Compiler.cpp | 2 +- .../vmIOandFlowOperationsTestFiller.json | 99 ++++++++++++++++++- 2 files changed, 97 insertions(+), 4 deletions(-) diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 58d8809d3..bf8a438a2 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -103,7 +103,7 @@ llvm::BasicBlock* Compiler::getJumpTableBlock() m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); auto dest = m_builder.CreatePHI(Type::Word, 8, "target"); auto switchInstr = m_builder.CreateSwitch(dest, m_abortBB); - for (auto&& p : m_basicBlocks) // FIXME: It mast be done at the end + for (auto&& p : m_basicBlocks) { if (p.second.isJumpDest()) switchInstr->addCase(Constant::get(p.first), p.second.llvm()); diff --git a/test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json b/test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json index ee68f0d67..95f2f4edb 100644 --- a/test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json +++ b/test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json @@ -140,7 +140,7 @@ "0x01" : "0x17" } } - }, + }, "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "100000000000000000000000", @@ -2211,6 +2211,99 @@ } }, + "DynamicJump_value1": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "100000000000000000000000", + "nonce" : "0", + "code" : "(asm 1 2 3 CALLVALUE JUMP + JUMPDEST POP POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST 0 MSTORE MSIZE 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "8", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + + "DynamicJump_value2": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "100000000000000000000000", + "nonce" : "0", + "code" : "(asm 1 2 3 CALLVALUE JUMP + JUMPDEST POP POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST 0 MSTORE MSIZE 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "18", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + + "DynamicJump_value3": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "100000000000000000000000", + "nonce" : "0", + "code" : "(asm 1 2 3 CALLVALUE JUMP + JUMPDEST POP POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST 0 MSTORE MSIZE 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "27", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + "BlockNumberDynamicJumpiAfterStop": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", @@ -2226,7 +2319,7 @@ "0x03" : "0x02" } } - }, + }, "pre" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "100000000000000000000000", @@ -3939,7 +4032,7 @@ "gas" : "100000" } }, - + "jumpi_at_the_end" : { "env" : { "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", From 7d1e35076f58e198502743082b8fe4c6034ea018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Jul 2015 14:54:35 +0200 Subject: [PATCH 09/41] Fix local stack max size calculation. --- evmjit/libevmjit/BasicBlock.cpp | 3 ++- evmjit/libevmjit/BasicBlock.h | 16 +++++++++------- evmjit/libevmjit/Compiler.cpp | 4 ++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/evmjit/libevmjit/BasicBlock.cpp b/evmjit/libevmjit/BasicBlock.cpp index f4f8b4645..d26203807 100644 --- a/evmjit/libevmjit/BasicBlock.cpp +++ b/evmjit/libevmjit/BasicBlock.cpp @@ -44,7 +44,7 @@ void LocalStack::push(llvm::Value* _value) { assert(_value->getType() == Type::Word); m_currentStack.push_back(_value); - m_maxSize = std::max(m_maxSize, m_currentStack.size()); // FIXME: This is wrong too. + add min size; + m_maxSize = std::max(m_maxSize, size()); } llvm::Value* LocalStack::pop() @@ -57,6 +57,7 @@ llvm::Value* LocalStack::pop() else ++m_globalPops; + m_minSize = std::min(m_minSize, size()); return item; } diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index 75b0efeab..044e9f687 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -36,11 +36,11 @@ public: /// @param _index Index of value to be swaped. Must be > 0. void swap(size_t _index); - ssize_t getDiff() const { return static_cast(m_currentStack.size()) - static_cast(m_globalPops); } - size_t getMaxSize() const { return m_maxSize; } + ssize_t size() const { return static_cast(m_currentStack.size()) - static_cast(m_globalPops); } + ssize_t minSize() const { return m_minSize; } + ssize_t maxSize() const { return m_maxSize; } - /// TODO: comment - /// TODO: It must be the same builder as in global stack. + /// Finalize local stack: check the requirements and update of the global stack. void finalize(llvm::IRBuilder<>& _builder, llvm::BasicBlock& _bb); private: @@ -63,9 +63,11 @@ private: /// top of the stack or changes existing items. std::vector m_currentStack; - size_t m_globalPops = 0; ///< Number of items poped from global stack. In other words: global - local stack overlap. - Stack& m_global; - size_t m_maxSize = 0; ///< Max size reached by the stack. + Stack& m_global; ///< Reference to global stack. + + size_t m_globalPops = 0; ///< Number of items poped from global stack. In other words: global - local stack overlap. + ssize_t m_minSize = 0; ///< Minimum reached local stack size. Can be negative. + ssize_t m_maxSize = 0; ///< Maximum reached local stack size. }; class BasicBlock diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index bf8a438a2..6002028dc 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -835,8 +835,8 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti stack.finalize(m_builder, *_basicBlock.llvm()); // TODO: Use references - m_builder.SetInsertPoint(_basicBlock.llvm()->getFirstNonPHI()); - _runtimeManager.checkStackLimit(stack.getMaxSize(), stack.getDiff()); + m_builder.SetInsertPoint(_basicBlock.llvm()->getFirstNonPHI()); // TODO: Move to LocalStack::finalize + _runtimeManager.checkStackLimit(stack.maxSize(), stack.size()); } From f4b79cfee76c84141550966307dd0dd96a524eb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Jul 2015 15:14:32 +0200 Subject: [PATCH 10/41] Do not remove dead blocks during compilation. --- evmjit/libevmjit/Compiler.cpp | 32 -------------------------------- evmjit/libevmjit/Compiler.h | 2 -- evmjit/libevmjit/Optimizer.cpp | 1 + 3 files changed, 1 insertion(+), 34 deletions(-) diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 6002028dc..056b5cabe 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -174,8 +174,6 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera m_builder.SetInsertPoint(m_abortBB); runtimeManager.exit(ReturnCode::OutOfGas); - removeDeadBlocks(); - // Link jump table target index if (m_jumpTableBlock) { @@ -840,36 +838,6 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti } -void Compiler::removeDeadBlocks() -{ - // Remove dead basic blocks - auto sthErased = false; - do - { - sthErased = false; - for (auto it = m_basicBlocks.begin(); it != m_basicBlocks.end();) - { - auto llvmBB = it->second.llvm(); - if (llvm::pred_begin(llvmBB) == llvm::pred_end(llvmBB)) - { - llvmBB->eraseFromParent(); - m_basicBlocks.erase(it++); - sthErased = true; - } - else - ++it; - } - } - while (sthErased); - - if (m_jumpTableBlock && llvm::pred_begin(m_jumpTableBlock->llvm()) == llvm::pred_end(m_jumpTableBlock->llvm())) - { - m_jumpTableBlock->llvm()->eraseFromParent(); - m_jumpTableBlock.reset(); - } -} - - } } } diff --git a/evmjit/libevmjit/Compiler.h b/evmjit/libevmjit/Compiler.h index a8cfa30e7..c7aea014e 100644 --- a/evmjit/libevmjit/Compiler.h +++ b/evmjit/libevmjit/Compiler.h @@ -36,8 +36,6 @@ private: llvm::BasicBlock* getJumpTableBlock(); - void removeDeadBlocks(); - /// Compiler options Options const& m_options; diff --git a/evmjit/libevmjit/Optimizer.cpp b/evmjit/libevmjit/Optimizer.cpp index dea3ea2a0..9cc6aa54a 100644 --- a/evmjit/libevmjit/Optimizer.cpp +++ b/evmjit/libevmjit/Optimizer.cpp @@ -114,6 +114,7 @@ bool LowerEVMPass::doFinalization(llvm::Module&) bool prepare(llvm::Module& _module) { auto pm = llvm::legacy::PassManager{}; + pm.add(llvm::createCFGSimplificationPass()); pm.add(llvm::createDeadCodeEliminationPass()); pm.add(new LowerEVMPass{}); return pm.run(_module); From f76d63476976cd81ca035ea9ef377e122216ac55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Jul 2015 16:22:04 +0200 Subject: [PATCH 11/41] Change the way Jump Table is created and filled. --- evmjit/libevmjit/BasicBlock.cpp | 5 --- evmjit/libevmjit/BasicBlock.h | 1 - evmjit/libevmjit/Compiler.cpp | 67 ++++++++++++++++----------------- evmjit/libevmjit/Compiler.h | 6 +-- 4 files changed, 36 insertions(+), 43 deletions(-) diff --git a/evmjit/libevmjit/BasicBlock.cpp b/evmjit/libevmjit/BasicBlock.cpp index d26203807..53bbe8b12 100644 --- a/evmjit/libevmjit/BasicBlock.cpp +++ b/evmjit/libevmjit/BasicBlock.cpp @@ -31,11 +31,6 @@ BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iter m_isJumpDest(isJumpDest) {} -BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, bool isJumpDest): - m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)), - m_isJumpDest(isJumpDest) -{} - LocalStack::LocalStack(Stack& _globalStack): m_global(_globalStack) {} diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index 044e9f687..ae2a0f584 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -74,7 +74,6 @@ class BasicBlock { public: explicit BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, bool isJumpDest); - explicit BasicBlock(std::string _name, llvm::Function* _mainFunc, bool isJumpDest); BasicBlock(const BasicBlock&) = delete; BasicBlock& operator=(const BasicBlock&) = delete; diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 056b5cabe..de2227521 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -94,22 +94,40 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn } } -llvm::BasicBlock* Compiler::getJumpTableBlock() +void Compiler::fillJumpTable() { - if (!m_jumpTableBlock) + assert(m_jumpTableBB); + + if (llvm::pred_empty(m_jumpTableBB)) { - m_jumpTableBlock.reset(new BasicBlock("JumpTable", m_mainFunc, true)); - InsertPointGuard g{m_builder}; - m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); - auto dest = m_builder.CreatePHI(Type::Word, 8, "target"); - auto switchInstr = m_builder.CreateSwitch(dest, m_abortBB); - for (auto&& p : m_basicBlocks) + m_jumpTableBB->eraseFromParent(); // remove if unused + return; + } + + m_builder.SetInsertPoint(m_jumpTableBB); + auto target = m_builder.CreatePHI(Type::Word, 16, "target"); + for (auto pred: llvm::predecessors(m_jumpTableBB)) + { + llvm::Value* incomingTarget = nullptr; + for (auto&& p: m_basicBlocks) // FIXME: Fix this stupid search. Use metadata to tag target in the basic block { - if (p.second.isJumpDest()) - switchInstr->addCase(Constant::get(p.first), p.second.llvm()); + if (p.second.llvm() == &*pred) + { + incomingTarget = p.second.getJumpTarget(); + break; + } } + + assert(incomingTarget); + target->addIncoming(incomingTarget, pred); + } + + auto switchInst = m_builder.CreateSwitch(target, m_abortBB); + for (auto& p: m_basicBlocks) + { + if (p.second.isJumpDest()) + switchInst->addCase(Constant::get(p.first), p.second.llvm()); } - return m_jumpTableBlock->llvm(); } std::unique_ptr Compiler::compile(code_iterator _begin, code_iterator _end, std::string const& _id) @@ -150,9 +168,9 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera auto normalFlow = m_builder.CreateICmpEQ(r, m_builder.getInt32(0)); runtimeManager.setJmpBuf(jmpBuf); - // TODO: Create Stop basic block on demand m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); m_abortBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Abort", m_mainFunc); + m_jumpTableBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "JumpTable", m_mainFunc); auto firstBB = m_basicBlocks.empty() ? m_stopBB : m_basicBlocks.begin()->second.llvm(); m_builder.CreateCondBr(normalFlow, firstBB, m_abortBB, Type::expectTrue); @@ -167,32 +185,13 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera } // Code for special blocks: - // TODO: move to separate function. m_builder.SetInsertPoint(m_stopBB); runtimeManager.exit(ReturnCode::Stop); m_builder.SetInsertPoint(m_abortBB); runtimeManager.exit(ReturnCode::OutOfGas); - // Link jump table target index - if (m_jumpTableBlock) - { - auto phi = llvm::cast(&m_jumpTableBlock->llvm()->getInstList().front()); - for (auto predIt = llvm::pred_begin(m_jumpTableBlock->llvm()); predIt != llvm::pred_end(m_jumpTableBlock->llvm()); ++predIt) - { - BasicBlock* pred = nullptr; - for (auto&& p : m_basicBlocks) - { - if (p.second.llvm() == *predIt) - { - pred = &p.second; - break; - } - } - - phi->addIncoming(pred->getJumpTarget(), pred->llvm()); - } - } + fillJumpTable(); return module; } @@ -592,7 +591,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti else { _basicBlock.setJumpTarget(target); - m_builder.CreateBr(getJumpTableBlock()); + m_builder.CreateBr(m_jumpTableBB); } } else // JUMPI @@ -608,7 +607,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti else { _basicBlock.setJumpTarget(target); - m_builder.CreateCondBr(cond, getJumpTableBlock(), _nextBasicBlock); + m_builder.CreateCondBr(cond, m_jumpTableBB, _nextBasicBlock); } } break; diff --git a/evmjit/libevmjit/Compiler.h b/evmjit/libevmjit/Compiler.h index c7aea014e..00a5047c5 100644 --- a/evmjit/libevmjit/Compiler.h +++ b/evmjit/libevmjit/Compiler.h @@ -34,7 +34,7 @@ private: void compileBasicBlock(BasicBlock& _basicBlock, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock, class Stack& _globalStack); - llvm::BasicBlock* getJumpTableBlock(); + void fillJumpTable(); /// Compiler options Options const& m_options; @@ -52,10 +52,10 @@ private: llvm::BasicBlock* m_abortBB = nullptr; /// Block with a jump table. - std::unique_ptr m_jumpTableBlock; + llvm::BasicBlock* m_jumpTableBB = nullptr; /// Main program function - llvm::Function* m_mainFunc = nullptr; + llvm::Function* m_mainFunc = nullptr; // TODO: Remove }; } From 406e13dadf001efae1ed91d33d5d75cd9b7b01e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Jul 2015 18:16:17 +0200 Subject: [PATCH 12/41] Use LLVM metadata for keeping information about jump target index. --- evmjit/libevmjit/BasicBlock.h | 6 ---- evmjit/libevmjit/Compiler.cpp | 55 +++++++++-------------------------- 2 files changed, 13 insertions(+), 48 deletions(-) diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index ae2a0f584..c79088ffc 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -86,9 +86,6 @@ public: bool isJumpDest() const { return m_isJumpDest; } - llvm::Value* getJumpTarget() const { return m_jumpTarget; } - void setJumpTarget(llvm::Value* _jumpTarget) { m_jumpTarget = _jumpTarget; } - private: instr_idx const m_firstInstrIdx = 0; ///< Code index of first instruction in the block code_iterator const m_begin = {}; ///< Iterator pointing code beginning of the block @@ -99,9 +96,6 @@ private: /// Is the basic block a valid jump destination. /// JUMPDEST is the first instruction of the basic block. bool const m_isJumpDest = false; - - /// If block finishes with dynamic jump target index is stored here - llvm::Value* m_jumpTarget = nullptr; }; } diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index de2227521..a04204812 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -108,18 +108,8 @@ void Compiler::fillJumpTable() auto target = m_builder.CreatePHI(Type::Word, 16, "target"); for (auto pred: llvm::predecessors(m_jumpTableBB)) { - llvm::Value* incomingTarget = nullptr; - for (auto&& p: m_basicBlocks) // FIXME: Fix this stupid search. Use metadata to tag target in the basic block - { - if (p.second.llvm() == &*pred) - { - incomingTarget = p.second.getJumpTarget(); - break; - } - } - - assert(incomingTarget); - target->addIncoming(incomingTarget, pred); + auto targetMd = llvm::cast(pred->getTerminator()->getMetadata("target")->getOperand(0)); + target->addIncoming(targetMd->getValue(), pred); } auto switchInst = m_builder.CreateSwitch(target, m_abortBB); @@ -571,44 +561,25 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti case Instruction::JUMP: case Instruction::JUMPI: { - llvm::BasicBlock* targetBlock = nullptr; + auto jumpBlock = m_jumpTableBB; auto target = stack.pop(); + auto jumpInst = (inst == Instruction::JUMP) ? + m_builder.CreateBr(jumpBlock) : + m_builder.CreateCondBr(m_builder.CreateICmpNE(stack.pop(), Constant::get(0), "jump.check"), jumpBlock, _nextBasicBlock); + if (auto constant = llvm::dyn_cast(target)) { + // If target index is a constant do direct jump to the target block. auto&& c = constant->getValue(); auto targetIdx = c.getActiveBits() <= 64 ? c.getZExtValue() : -1; auto it = m_basicBlocks.find(targetIdx); - targetBlock = (it != m_basicBlocks.end() && it->second.isJumpDest()) ? it->second.llvm() : m_abortBB; - } - - // TODO: Improve; check for constants - if (inst == Instruction::JUMP) - { - if (targetBlock) - { - m_builder.CreateBr(targetBlock); - } - else - { - _basicBlock.setJumpTarget(target); - m_builder.CreateBr(m_jumpTableBB); - } + jumpInst->setSuccessor(0, (it != m_basicBlocks.end() && it->second.isJumpDest()) ? it->second.llvm() : m_abortBB); } - else // JUMPI + else { - auto val = stack.pop(); - auto zero = Constant::get(0); - auto cond = m_builder.CreateICmpNE(val, zero, "nonzero"); - - if (targetBlock) - { - m_builder.CreateCondBr(cond, targetBlock, _nextBasicBlock); - } - else - { - _basicBlock.setJumpTarget(target); - m_builder.CreateCondBr(cond, m_jumpTableBB, _nextBasicBlock); - } + // Attach medatada to branch instruction with information about target index. + auto targetMd = llvm::MDNode::get(jumpInst->getContext(), llvm::LocalAsMetadata::get(target)); + jumpInst->setMetadata("target", targetMd); } break; } From 1de60c02e685f9b453ee02443c141c3502979df6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Jul 2015 18:48:58 +0200 Subject: [PATCH 13/41] Add test for global stack underflow. --- evmjit/libevmjit/Stack.cpp | 3 +- .../vmIOandFlowOperationsTestFiller.json | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/evmjit/libevmjit/Stack.cpp b/evmjit/libevmjit/Stack.cpp index b7b8f25b1..b83849a92 100644 --- a/evmjit/libevmjit/Stack.cpp +++ b/evmjit/libevmjit/Stack.cpp @@ -71,8 +71,7 @@ void Stack::set(size_t _index, llvm::Value* _value) void Stack::pop(size_t _count) { - // FIXME: Pop does not check for stack underflow but looks like not needed - // We should place stack.require() check and begining of every BB + // TODO: We should place stack.require() check and begining of every BB m_stack.pop(m_builder.getInt64(_count)); } diff --git a/test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json b/test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json index 95f2f4edb..0c6801dd0 100644 --- a/test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json +++ b/test/libevm/VMTestsFiller/vmIOandFlowOperationsTestFiller.json @@ -2304,6 +2304,37 @@ } }, + "DynamicJump_valueUnderflow": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "1000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "100000000000000000000000", + "nonce" : "0", + "code" : "(asm 1 2 3 CALLVALUE JUMP + JUMPDEST POP POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST POP 0 MSTORE MSIZE 0 RETURN + JUMPDEST POP POP POP 0 MSTORE MSIZE 0 RETURN)", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "27", + "data" : "", + "gasPrice" : "100000000000000", + "gas" : "100000" + } + }, + "BlockNumberDynamicJumpiAfterStop": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", From 4a68a237b0c79db0a819c0d4d16eb355e6b493aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Jul 2015 18:58:24 +0200 Subject: [PATCH 14/41] Rename private members of LocalStack. --- evmjit/libevmjit/BasicBlock.cpp | 40 ++++++++++++++++----------------- evmjit/libevmjit/BasicBlock.h | 22 ++++++------------ 2 files changed, 27 insertions(+), 35 deletions(-) diff --git a/evmjit/libevmjit/BasicBlock.cpp b/evmjit/libevmjit/BasicBlock.cpp index 53bbe8b12..b9534e40f 100644 --- a/evmjit/libevmjit/BasicBlock.cpp +++ b/evmjit/libevmjit/BasicBlock.cpp @@ -38,17 +38,17 @@ LocalStack::LocalStack(Stack& _globalStack): void LocalStack::push(llvm::Value* _value) { assert(_value->getType() == Type::Word); - m_currentStack.push_back(_value); + m_local.push_back(_value); m_maxSize = std::max(m_maxSize, size()); } llvm::Value* LocalStack::pop() { auto item = get(0); - assert(!m_currentStack.empty() || !m_initialStack.empty()); + assert(!m_local.empty() || !m_input.empty()); - if (m_currentStack.size() > 0) - m_currentStack.pop_back(); + if (m_local.size() > 0) + m_local.pop_back(); else ++m_globalPops; @@ -80,13 +80,13 @@ void LocalStack::swap(size_t _index) llvm::Value* LocalStack::get(size_t _index) { - if (_index < m_currentStack.size()) - return *(m_currentStack.rbegin() + _index); // count from back + if (_index < m_local.size()) + return *(m_local.rbegin() + _index); // count from back - auto idx = _index - m_currentStack.size() + m_globalPops; - if (idx >= m_initialStack.size()) - m_initialStack.resize(idx + 1); - auto& item = m_initialStack[idx]; + auto idx = _index - m_local.size() + m_globalPops; + if (idx >= m_input.size()) + m_input.resize(idx + 1); + auto& item = m_input[idx]; if (!item) item = m_global.get(idx); @@ -96,15 +96,15 @@ llvm::Value* LocalStack::get(size_t _index) void LocalStack::set(size_t _index, llvm::Value* _word) { - if (_index < m_currentStack.size()) + if (_index < m_local.size()) { - *(m_currentStack.rbegin() + _index) = _word; + *(m_local.rbegin() + _index) = _word; return; } - auto idx = _index - m_currentStack.size() + m_globalPops; - assert(idx < m_initialStack.size()); - m_initialStack[idx] = _word; + auto idx = _index - m_local.size() + m_globalPops; + assert(idx < m_input.size()); + m_input[idx] = _word; } @@ -118,15 +118,15 @@ void LocalStack::finalize(llvm::IRBuilder<>& _builder, llvm::BasicBlock& _bb) _builder.SetInsertPoint(blockTerminator); // Update items fetched from global stack ignoring the poped ones - assert(m_globalPops <= m_initialStack.size()); // pop() always does get() - for (auto i = m_globalPops; i < m_initialStack.size(); ++i) + assert(m_globalPops <= m_input.size()); // pop() always does get() + for (auto i = m_globalPops; i < m_input.size(); ++i) { - if (m_initialStack[i]) - m_global.set(i, m_initialStack[i]); + if (m_input[i]) + m_global.set(i, m_input[i]); } // Add new items - for (auto& item: m_currentStack) + for (auto& item: m_local) { if (m_globalPops) // Override poped global items m_global.set(--m_globalPops, item); // using pops counter as the index diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index c79088ffc..14c7111f8 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -14,8 +14,6 @@ namespace jit using namespace evmjit; using instr_idx = uint64_t; -class BasicBlock; - class LocalStack { public: @@ -36,7 +34,7 @@ public: /// @param _index Index of value to be swaped. Must be > 0. void swap(size_t _index); - ssize_t size() const { return static_cast(m_currentStack.size()) - static_cast(m_globalPops); } + ssize_t size() const { return static_cast(m_local.size()) - static_cast(m_globalPops); } ssize_t minSize() const { return m_minSize; } ssize_t maxSize() const { return m_maxSize; } @@ -50,18 +48,12 @@ private: /// Sets _index'th value from top (counting from 0) void set(size_t _index, llvm::Value* _value); - /// This stack contains LLVM values that correspond to items found at - /// the EVM stack when the current basic block starts executing. - /// Location 0 corresponds to the top of the EVM stack, location 1 is - /// the item below the top and so on. The stack grows as the code - /// accesses more items on the EVM stack but once a value is put on - /// the stack, it will never be replaced. - std::vector m_initialStack; - - /// This stack tracks the contents of the EVM stack as the basic block - /// executes. It may grow on both sides, as the code pushes items on - /// top of the stack or changes existing items. - std::vector m_currentStack; + /// Items fetched from global stack. First element matches the top of the global stack. + /// Can contain nulls if some items has been skipped. + std::vector m_input; + + /// Local stack items that has not been pushed to global stack. First item is just above global stack. + std::vector m_local; Stack& m_global; ///< Reference to global stack. From b44d4846f5799b7d8a3ca6a5cf4ccdb15a2f4823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Jul 2015 20:48:09 +0200 Subject: [PATCH 15/41] Use llvm::SwitchInstr as a jump dest map. --- evmjit/libevmjit/BasicBlock.cpp | 3 +-- evmjit/libevmjit/BasicBlock.h | 6 ----- evmjit/libevmjit/Compiler.cpp | 43 +++++++++++++++------------------ evmjit/libevmjit/Compiler.h | 5 ++-- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/evmjit/libevmjit/BasicBlock.cpp b/evmjit/libevmjit/BasicBlock.cpp index b9534e40f..7ec68813a 100644 --- a/evmjit/libevmjit/BasicBlock.cpp +++ b/evmjit/libevmjit/BasicBlock.cpp @@ -27,8 +27,7 @@ BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iter m_firstInstrIdx{_firstInstrIdx}, m_begin(_begin), m_end(_end), - m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {isJumpDest ? jumpDestName : basicBlockName, std::to_string(_firstInstrIdx)}, _mainFunc)), - m_isJumpDest(isJumpDest) + m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {isJumpDest ? jumpDestName : basicBlockName, std::to_string(_firstInstrIdx)}, _mainFunc)) {} LocalStack::LocalStack(Stack& _globalStack): diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index 14c7111f8..8a23426c1 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -76,18 +76,12 @@ public: code_iterator begin() const { return m_begin; } code_iterator end() const { return m_end; } - bool isJumpDest() const { return m_isJumpDest; } - private: instr_idx const m_firstInstrIdx = 0; ///< Code index of first instruction in the block code_iterator const m_begin = {}; ///< Iterator pointing code beginning of the block code_iterator const m_end = {}; ///< Iterator pointing code end of the block llvm::BasicBlock* const m_llvmBB; - - /// Is the basic block a valid jump destination. - /// JUMPDEST is the first instruction of the basic block. - bool const m_isJumpDest = false; }; } diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index a04204812..3c79bbdcb 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -36,7 +36,7 @@ Compiler::Compiler(Options const& _options): Type::init(m_builder.getContext()); } -void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEnd) +void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEnd, llvm::SwitchInst& _jumpTable) { /// Helper function that skips push data and finds next iterator (can be the end) auto skipPushDataAndGetNext = [](code_iterator _curr, code_iterator _end) @@ -86,8 +86,10 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn if (isEnd) { auto beginIdx = begin - _codeBegin; - m_basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginIdx), + auto r = m_basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginIdx), std::forward_as_tuple(beginIdx, begin, next, m_mainFunc, nextJumpDest)); + if (nextJumpDest) + _jumpTable.addCase(Constant::get(beginIdx), r.first->second.llvm()); nextJumpDest = false; begin = next; } @@ -97,27 +99,19 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn void Compiler::fillJumpTable() { assert(m_jumpTableBB); - if (llvm::pred_empty(m_jumpTableBB)) { m_jumpTableBB->eraseFromParent(); // remove if unused return; } - m_builder.SetInsertPoint(m_jumpTableBB); - auto target = m_builder.CreatePHI(Type::Word, 16, "target"); + // TODO: Extend this function as `resolveJumps()` and fill gaps in branch instructions. + auto target = llvm::cast(m_jumpTableBB->begin()); for (auto pred: llvm::predecessors(m_jumpTableBB)) { auto targetMd = llvm::cast(pred->getTerminator()->getMetadata("target")->getOperand(0)); target->addIncoming(targetMd->getValue(), pred); } - - auto switchInst = m_builder.CreateSwitch(target, m_abortBB); - for (auto& p: m_basicBlocks) - { - if (p.second.isJumpDest()) - switchInst->addCase(Constant::get(p.first), p.second.llvm()); - } } std::unique_ptr Compiler::compile(code_iterator _begin, code_iterator _end, std::string const& _id) @@ -131,9 +125,17 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera // Create entry basic block auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), {}, m_mainFunc); + + m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); + m_abortBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Abort", m_mainFunc); + m_jumpTableBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "JumpTable", m_mainFunc); + m_builder.SetInsertPoint(m_jumpTableBB); + auto target = m_builder.CreatePHI(Type::Word, 16, "target"); + auto& jumpTable = *m_builder.CreateSwitch(target, m_abortBB); + m_builder.SetInsertPoint(entryBlock); - createBasicBlocks(_begin, _end); + createBasicBlocks(_begin, _end, jumpTable); // Init runtime structures. RuntimeManager runtimeManager(m_builder, _begin, _end); @@ -158,10 +160,6 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera auto normalFlow = m_builder.CreateICmpEQ(r, m_builder.getInt32(0)); runtimeManager.setJmpBuf(jmpBuf); - m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); - m_abortBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Abort", m_mainFunc); - m_jumpTableBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "JumpTable", m_mainFunc); - auto firstBB = m_basicBlocks.empty() ? m_stopBB : m_basicBlocks.begin()->second.llvm(); m_builder.CreateCondBr(normalFlow, firstBB, m_abortBB, Type::expectTrue); @@ -171,7 +169,7 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera auto iterCopy = basicBlockPairIt; ++iterCopy; auto nextBasicBlock = (iterCopy != m_basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; - compileBasicBlock(basicBlock, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock, stack); + compileBasicBlock(basicBlock, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock, stack, jumpTable); } // Code for special blocks: @@ -188,7 +186,8 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runtimeManager, - Arith256& _arith, Memory& _memory, Ext& _ext, GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock, Stack& _globalStack) + Arith256& _arith, Memory& _memory, Ext& _ext, GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock, Stack& _globalStack, + llvm::SwitchInst& jumpTable) { if (!_nextBasicBlock) // this is the last block in the code _nextBasicBlock = m_stopBB; @@ -570,10 +569,8 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti if (auto constant = llvm::dyn_cast(target)) { // If target index is a constant do direct jump to the target block. - auto&& c = constant->getValue(); - auto targetIdx = c.getActiveBits() <= 64 ? c.getZExtValue() : -1; - auto it = m_basicBlocks.find(targetIdx); - jumpInst->setSuccessor(0, (it != m_basicBlocks.end() && it->second.isJumpDest()) ? it->second.llvm() : m_abortBB); + auto bb = jumpTable.findCaseValue(constant).getCaseSuccessor(); + jumpInst->setSuccessor(0, bb); } else { diff --git a/evmjit/libevmjit/Compiler.h b/evmjit/libevmjit/Compiler.h index 00a5047c5..b14ef13ae 100644 --- a/evmjit/libevmjit/Compiler.h +++ b/evmjit/libevmjit/Compiler.h @@ -30,9 +30,10 @@ public: private: - void createBasicBlocks(code_iterator _begin, code_iterator _end); + void createBasicBlocks(code_iterator _begin, code_iterator _end, llvm::SwitchInst& _switchInst); - void compileBasicBlock(BasicBlock& _basicBlock, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock, class Stack& _globalStack); + void compileBasicBlock(BasicBlock& _basicBlock, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, + llvm::BasicBlock* _nextBasicBlock, class Stack& _globalStack, llvm::SwitchInst& _jumpTable); void fillJumpTable(); From 61233522953235c0e8160375b20bc809b5173ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Jul 2015 21:06:28 +0200 Subject: [PATCH 16/41] Replace map of basic blocks with vector. --- evmjit/libevmjit/BasicBlock.h | 4 ++-- evmjit/libevmjit/Compiler.cpp | 12 ++++++------ evmjit/libevmjit/Compiler.h | 4 +--- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index 8a23426c1..24cd74cbe 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -67,8 +67,8 @@ class BasicBlock public: explicit BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, bool isJumpDest); - BasicBlock(const BasicBlock&) = delete; - BasicBlock& operator=(const BasicBlock&) = delete; + BasicBlock(BasicBlock&&) = default; + BasicBlock& operator=(BasicBlock&&) = default; llvm::BasicBlock* llvm() { return m_llvmBB; } diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 3c79bbdcb..66f347912 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -86,10 +86,9 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn if (isEnd) { auto beginIdx = begin - _codeBegin; - auto r = m_basicBlocks.emplace(std::piecewise_construct, std::forward_as_tuple(beginIdx), - std::forward_as_tuple(beginIdx, begin, next, m_mainFunc, nextJumpDest)); + m_basicBlocks.emplace_back(beginIdx, begin, next, m_mainFunc, nextJumpDest); if (nextJumpDest) - _jumpTable.addCase(Constant::get(beginIdx), r.first->second.llvm()); + _jumpTable.addCase(Constant::get(beginIdx), m_basicBlocks.back().llvm()); nextJumpDest = false; begin = next; } @@ -160,15 +159,16 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera auto normalFlow = m_builder.CreateICmpEQ(r, m_builder.getInt32(0)); runtimeManager.setJmpBuf(jmpBuf); - auto firstBB = m_basicBlocks.empty() ? m_stopBB : m_basicBlocks.begin()->second.llvm(); + auto firstBB = m_basicBlocks.empty() ? m_stopBB : m_basicBlocks.front().llvm(); m_builder.CreateCondBr(normalFlow, firstBB, m_abortBB, Type::expectTrue); for (auto basicBlockPairIt = m_basicBlocks.begin(); basicBlockPairIt != m_basicBlocks.end(); ++basicBlockPairIt) { - auto& basicBlock = basicBlockPairIt->second; + // TODO: Rewrite + auto& basicBlock = *basicBlockPairIt; auto iterCopy = basicBlockPairIt; ++iterCopy; - auto nextBasicBlock = (iterCopy != m_basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; + auto nextBasicBlock = (iterCopy != m_basicBlocks.end()) ? iterCopy->llvm() : nullptr; compileBasicBlock(basicBlock, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock, stack, jumpTable); } diff --git a/evmjit/libevmjit/Compiler.h b/evmjit/libevmjit/Compiler.h index b14ef13ae..0a6e050d5 100644 --- a/evmjit/libevmjit/Compiler.h +++ b/evmjit/libevmjit/Compiler.h @@ -22,8 +22,6 @@ public: bool dumpCFG = false; }; - using ProgramCounter = uint64_t; - Compiler(Options const& _options); std::unique_ptr compile(code_iterator _begin, code_iterator _end, std::string const& _id); @@ -44,7 +42,7 @@ private: llvm::IRBuilder<> m_builder; /// Maps a program counter pc to a basic block that starts at pc (if any). - std::map m_basicBlocks; + std::vector m_basicBlocks; /// Stop basic block - terminates execution with STOP code (0) llvm::BasicBlock* m_stopBB = nullptr; From 215ea7dde5d875d8163d85d220ffdbcff24f23e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Jul 2015 21:19:58 +0200 Subject: [PATCH 17/41] Remove vector of basic blocks from Compiler. --- evmjit/libevmjit/BasicBlock.cpp | 7 ++----- evmjit/libevmjit/BasicBlock.h | 2 +- evmjit/libevmjit/Compiler.cpp | 32 ++++++++++++++------------------ evmjit/libevmjit/Compiler.h | 5 +---- 4 files changed, 18 insertions(+), 28 deletions(-) diff --git a/evmjit/libevmjit/BasicBlock.cpp b/evmjit/libevmjit/BasicBlock.cpp index 7ec68813a..69a7a91d6 100644 --- a/evmjit/libevmjit/BasicBlock.cpp +++ b/evmjit/libevmjit/BasicBlock.cpp @@ -20,14 +20,11 @@ namespace eth namespace jit { -static const char* jumpDestName = "JmpDst."; -static const char* basicBlockName = "Instr."; - -BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, bool isJumpDest): +BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc): m_firstInstrIdx{_firstInstrIdx}, m_begin(_begin), m_end(_end), - m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {isJumpDest ? jumpDestName : basicBlockName, std::to_string(_firstInstrIdx)}, _mainFunc)) + m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {"Instr.", std::to_string(_firstInstrIdx)}, _mainFunc)) {} LocalStack::LocalStack(Stack& _globalStack): diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index 24cd74cbe..a8394e7cc 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -65,7 +65,7 @@ private: class BasicBlock { public: - explicit BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, bool isJumpDest); + explicit BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc); BasicBlock(BasicBlock&&) = default; BasicBlock& operator=(BasicBlock&&) = default; diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 66f347912..0ca01a199 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -36,7 +36,7 @@ Compiler::Compiler(Options const& _options): Type::init(m_builder.getContext()); } -void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEnd, llvm::SwitchInst& _jumpTable) +std::vector Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEnd, llvm::SwitchInst& _jumpTable) { /// Helper function that skips push data and finds next iterator (can be the end) auto skipPushDataAndGetNext = [](code_iterator _curr, code_iterator _end) @@ -54,8 +54,9 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn if (*(_codeEnd - 1) != static_cast(Instruction::STOP)) break; + std::vector blocks; + auto begin = _codeBegin; // begin of current block - bool nextJumpDest = false; for (auto curr = begin, next = begin; curr != _codeEnd; curr = next) { next = skipPushDataAndGetNext(curr, _codeEnd); @@ -71,10 +72,6 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn isEnd = true; break; - case Instruction::JUMPDEST: - nextJumpDest = true; - break; - default: break; } @@ -86,13 +83,14 @@ void Compiler::createBasicBlocks(code_iterator _codeBegin, code_iterator _codeEn if (isEnd) { auto beginIdx = begin - _codeBegin; - m_basicBlocks.emplace_back(beginIdx, begin, next, m_mainFunc, nextJumpDest); - if (nextJumpDest) - _jumpTable.addCase(Constant::get(beginIdx), m_basicBlocks.back().llvm()); - nextJumpDest = false; + blocks.emplace_back(beginIdx, begin, next, m_mainFunc); + if (Instruction(*begin) == Instruction::JUMPDEST) + _jumpTable.addCase(Constant::get(beginIdx), blocks.back().llvm()); begin = next; } } + + return blocks; } void Compiler::fillJumpTable() @@ -134,7 +132,7 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera m_builder.SetInsertPoint(entryBlock); - createBasicBlocks(_begin, _end, jumpTable); + auto blocks = createBasicBlocks(_begin, _end, jumpTable); // Init runtime structures. RuntimeManager runtimeManager(m_builder, _begin, _end); @@ -159,17 +157,15 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera auto normalFlow = m_builder.CreateICmpEQ(r, m_builder.getInt32(0)); runtimeManager.setJmpBuf(jmpBuf); - auto firstBB = m_basicBlocks.empty() ? m_stopBB : m_basicBlocks.front().llvm(); + auto firstBB = blocks.empty() ? m_stopBB : blocks.front().llvm(); m_builder.CreateCondBr(normalFlow, firstBB, m_abortBB, Type::expectTrue); - for (auto basicBlockPairIt = m_basicBlocks.begin(); basicBlockPairIt != m_basicBlocks.end(); ++basicBlockPairIt) + for (auto it = blocks.begin(); it != blocks.end(); ++it) { // TODO: Rewrite - auto& basicBlock = *basicBlockPairIt; - auto iterCopy = basicBlockPairIt; - ++iterCopy; - auto nextBasicBlock = (iterCopy != m_basicBlocks.end()) ? iterCopy->llvm() : nullptr; - compileBasicBlock(basicBlock, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock, stack, jumpTable); + auto nextIt = it + 1; + auto nextBasicBlock = (nextIt != blocks.end()) ? nextIt->llvm() : nullptr; // TODO: What with Stop block? + compileBasicBlock(*it, runtimeManager, arith, memory, ext, gasMeter, nextBasicBlock, stack, jumpTable); } // Code for special blocks: diff --git a/evmjit/libevmjit/Compiler.h b/evmjit/libevmjit/Compiler.h index 0a6e050d5..af45acedb 100644 --- a/evmjit/libevmjit/Compiler.h +++ b/evmjit/libevmjit/Compiler.h @@ -28,7 +28,7 @@ public: private: - void createBasicBlocks(code_iterator _begin, code_iterator _end, llvm::SwitchInst& _switchInst); + std::vector createBasicBlocks(code_iterator _begin, code_iterator _end, llvm::SwitchInst& _switchInst); void compileBasicBlock(BasicBlock& _basicBlock, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock, class Stack& _globalStack, llvm::SwitchInst& _jumpTable); @@ -41,9 +41,6 @@ private: /// Helper class for generating IR llvm::IRBuilder<> m_builder; - /// Maps a program counter pc to a basic block that starts at pc (if any). - std::vector m_basicBlocks; - /// Stop basic block - terminates execution with STOP code (0) llvm::BasicBlock* m_stopBB = nullptr; From c8846eb01a88630ec8e768805438c71863725dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 11 Aug 2015 10:21:07 +0200 Subject: [PATCH 18/41] Do not modify pops counter of LocalStack during finalization. That fixes LocalStack::size() returning incorrect values after LocalStack::finalize() has been called. --- evmjit/libevmjit/BasicBlock.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/evmjit/libevmjit/BasicBlock.cpp b/evmjit/libevmjit/BasicBlock.cpp index 69a7a91d6..a60d1ba35 100644 --- a/evmjit/libevmjit/BasicBlock.cpp +++ b/evmjit/libevmjit/BasicBlock.cpp @@ -122,17 +122,18 @@ void LocalStack::finalize(llvm::IRBuilder<>& _builder, llvm::BasicBlock& _bb) } // Add new items + auto pops = m_globalPops; // Copy pops counter to keep original value for (auto& item: m_local) { - if (m_globalPops) // Override poped global items - m_global.set(--m_globalPops, item); // using pops counter as the index + if (pops) // Override poped global items + m_global.set(--pops, item); // using pops counter as the index else m_global.push(item); } // Pop not overriden items - if (m_globalPops) - m_global.pop(m_globalPops); + if (pops) + m_global.pop(pops); } } From 94b3c55c7f8765a97863d6bb0843ff6229b76bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 11 Aug 2015 11:01:19 +0200 Subject: [PATCH 19/41] Remove explicit move constructor of BasicBlock. --- evmjit/libevmjit/BasicBlock.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/evmjit/libevmjit/BasicBlock.h b/evmjit/libevmjit/BasicBlock.h index baf3ffc34..a6e420efc 100644 --- a/evmjit/libevmjit/BasicBlock.h +++ b/evmjit/libevmjit/BasicBlock.h @@ -67,9 +67,6 @@ class BasicBlock public: explicit BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc); - BasicBlock(BasicBlock&&) = default; - BasicBlock& operator=(BasicBlock&&) = default; - llvm::BasicBlock* llvm() { return m_llvmBB; } instr_idx firstInstrIdx() const { return m_firstInstrIdx; } @@ -78,10 +75,10 @@ public: private: instr_idx const m_firstInstrIdx = 0; ///< Code index of first instruction in the block - code_iterator const m_begin = {}; ///< Iterator pointing code beginning of the block - code_iterator const m_end = {}; ///< Iterator pointing code end of the block + code_iterator const m_begin = {}; ///< Iterator pointing code beginning of the block + code_iterator const m_end = {}; ///< Iterator pointing code end of the block - llvm::BasicBlock* const m_llvmBB; + llvm::BasicBlock* const m_llvmBB; ///< Reference to the LLVM BasicBlock }; } From 864a3540a4e4034f57075dc4ddae8fba1aa2c2f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 12 Aug 2015 13:39:46 +0200 Subject: [PATCH 20/41] Clean up LazyFunction initialization in Array helper. --- evmjit/libevmjit/Array.cpp | 12 ++---------- evmjit/libevmjit/Array.h | 8 +++----- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/evmjit/libevmjit/Array.cpp b/evmjit/libevmjit/Array.cpp index 96329afd5..4f1f47d6e 100644 --- a/evmjit/libevmjit/Array.cpp +++ b/evmjit/libevmjit/Array.cpp @@ -217,11 +217,7 @@ llvm::Type* Array::getType() } Array::Array(llvm::IRBuilder<>& _builder, char const* _name) : - CompilerHelper(_builder), - m_pushFunc([this](){ return createArrayPushFunc(); }), - m_setFunc([this](){ return createArraySetFunc(); }), - m_getFunc([this](){ return createArrayGetFunc(); }), - m_freeFunc([this](){ return createFreeFunc(); }) + CompilerHelper(_builder) { m_array = m_builder.CreateAlloca(getType(), nullptr, _name); m_builder.CreateStore(llvm::ConstantAggregateZero::get(getType()), m_array); @@ -229,11 +225,7 @@ Array::Array(llvm::IRBuilder<>& _builder, char const* _name) : Array::Array(llvm::IRBuilder<>& _builder, llvm::Value* _array) : CompilerHelper(_builder), - m_array(_array), - m_pushFunc([this](){ return createArrayPushFunc(); }), - m_setFunc([this](){ return createArraySetFunc(); }), - m_getFunc([this](){ return createArrayGetFunc(); }), - m_freeFunc([this](){ return createFreeFunc(); }) + m_array(_array) { m_builder.CreateStore(llvm::ConstantAggregateZero::get(getType()), m_array); } diff --git a/evmjit/libevmjit/Array.h b/evmjit/libevmjit/Array.h index 41842f0c9..a2db976b3 100644 --- a/evmjit/libevmjit/Array.h +++ b/evmjit/libevmjit/Array.h @@ -59,10 +59,10 @@ private: llvm::Function* getReallocFunc(); LazyFunction m_pushFunc = {[this](){ return createArrayPushFunc(); }}; // TODO: If works on MSVC, remove form initialization list - LazyFunction m_setFunc; + LazyFunction m_setFunc = {[this](){ return createArraySetFunc(); }}; LazyFunction m_getPtrFunc = {[this](){ return createGetPtrFunc(); }}; - LazyFunction m_getFunc; - LazyFunction m_freeFunc; + LazyFunction m_getFunc = {[this](){ return createArrayGetFunc(); }}; + LazyFunction m_freeFunc = {[this](){ return createFreeFunc(); }}; LazyFunction m_extendFunc = {[this](){ return createExtendFunc(); }}; LazyFunction m_reallocFunc = {[this](){ return getReallocFunc(); }}; }; @@ -70,5 +70,3 @@ private: } } } - - From 5507cc870a51d513cd9dfb29d845c487f2c1d4a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 12 Aug 2015 14:37:14 +0200 Subject: [PATCH 21/41] Check also stack underflow in evm.stack.require() function. --- evmjit/libevmjit/Compiler.cpp | 2 +- evmjit/libevmjit/RuntimeManager.cpp | 19 ++++++++++++------- evmjit/libevmjit/RuntimeManager.h | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 50f9833f4..30437b6a3 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -797,7 +797,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, RuntimeManager& _runti stack.finalize(m_builder, *_basicBlock.llvm()); // TODO: Use references m_builder.SetInsertPoint(_basicBlock.llvm()->getFirstNonPHI()); // TODO: Move to LocalStack::finalize - _runtimeManager.checkStackLimit(stack.maxSize(), stack.size()); + _runtimeManager.checkStackLimit(stack.minSize(), stack.maxSize(), stack.size()); } diff --git a/evmjit/libevmjit/RuntimeManager.cpp b/evmjit/libevmjit/RuntimeManager.cpp index b55d90a1a..bce378b64 100644 --- a/evmjit/libevmjit/RuntimeManager.cpp +++ b/evmjit/libevmjit/RuntimeManager.cpp @@ -110,8 +110,8 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB m_gasPtr = m_builder.CreateAlloca(Type::Gas, nullptr, "gas.ptr"); m_builder.CreateStore(m_dataElts[RuntimeData::Index::Gas], m_gasPtr); - llvm::Type* checkStackLimitArgs[] = {Type::Size->getPointerTo(), Type::Size, Type::Size, Type::BytePtr}; - m_checkStackLimit = llvm::Function::Create(llvm::FunctionType::get(Type::Void, checkStackLimitArgs, false), llvm::Function::PrivateLinkage, "stack.checkSize", getModule()); + llvm::Type* checkStackLimitArgs[] = {Type::Size->getPointerTo(), Type::Size, Type::Size, Type::Size, Type::BytePtr}; + m_checkStackLimit = llvm::Function::Create(llvm::FunctionType::get(Type::Void, checkStackLimitArgs, false), llvm::Function::PrivateLinkage, "evm.stack.require", getModule()); m_checkStackLimit->setDoesNotThrow(); m_checkStackLimit->setDoesNotCapture(1); @@ -121,7 +121,9 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB auto currSizePtr = &m_checkStackLimit->getArgumentList().front(); currSizePtr->setName("currSize"); - auto max = currSizePtr->getNextNode(); + auto min = currSizePtr->getNextNode(); + min->setName("min"); + auto max = min->getNextNode(); max->setName("max"); auto diff = max->getNextNode(); diff->setName("diff"); @@ -131,8 +133,11 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB InsertPointGuard guard{m_builder}; m_builder.SetInsertPoint(checkBB); auto currSize = m_builder.CreateLoad(currSizePtr, "cur"); - auto maxSize = m_builder.CreateNUWAdd(currSize, max, "maxSize"); - auto ok = m_builder.CreateICmpULE(maxSize, m_builder.getInt64(1024), "ok"); + auto minSize = m_builder.CreateAdd(currSize, min, "minSize", false, true); + auto maxSize = m_builder.CreateAdd(currSize, max, "maxSize", true, true); + auto minOk = m_builder.CreateICmpSGE(minSize, m_builder.getInt64(0), "min.ok"); + auto maxOk = m_builder.CreateICmpULE(maxSize, m_builder.getInt64(1024), "max.ok"); + auto ok = m_builder.CreateAnd(minOk, maxOk, "ok"); m_builder.CreateCondBr(ok, updateBB, outOfStackBB, Type::expectTrue); m_builder.SetInsertPoint(updateBB); @@ -145,9 +150,9 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeB m_builder.CreateUnreachable(); } -void RuntimeManager::checkStackLimit(size_t _max, ssize_t _diff) +void RuntimeManager::checkStackLimit(ssize_t _min, ssize_t _max, ssize_t _diff) { - createCall(m_checkStackLimit, {m_stackSize, m_builder.getInt64(_max), m_builder.getInt64(_diff), getJmpBuf()}); + createCall(m_checkStackLimit, {m_stackSize, m_builder.getInt64(_min), m_builder.getInt64(_max), m_builder.getInt64(_diff), getJmpBuf()}); } llvm::Value* RuntimeManager::getRuntimePtr() diff --git a/evmjit/libevmjit/RuntimeManager.h b/evmjit/libevmjit/RuntimeManager.h index aa8f4838b..8511c8898 100644 --- a/evmjit/libevmjit/RuntimeManager.h +++ b/evmjit/libevmjit/RuntimeManager.h @@ -50,7 +50,7 @@ public: static llvm::StructType* getRuntimeType(); static llvm::StructType* getRuntimeDataType(); - void checkStackLimit(size_t _max, ssize_t _diff); + void checkStackLimit(ssize_t _min, ssize_t _max, ssize_t _diff); private: llvm::Value* getPtr(RuntimeData::Index _index); From 4904c602b01b307fe46197c53fae1fe993301019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 12 Aug 2015 14:50:11 +0200 Subject: [PATCH 22/41] "Tweak" version component. Add "tweak" component for evmjit version to control cached objects. Bump version to 0.9.0.1. --- evmjit/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/evmjit/CMakeLists.txt b/evmjit/CMakeLists.txt index 619477119..49bf7f73d 100644 --- a/evmjit/CMakeLists.txt +++ b/evmjit/CMakeLists.txt @@ -3,13 +3,14 @@ cmake_minimum_required(VERSION 2.8.12) if (${CMAKE_VERSION} VERSION_GREATER 3.0) cmake_policy(SET CMP0042 OLD) # fix MACOSX_RPATH cmake_policy(SET CMP0048 NEW) # allow VERSION argument in project() - project(EVMJIT VERSION 0.9.0 LANGUAGES CXX) + project(EVMJIT VERSION 0.9.0.1 LANGUAGES CXX) else() project(EVMJIT) - set(EVMJIT_VERSION "0.9.0") + set(EVMJIT_VERSION "0.9.0.1") set(EVMJIT_VERSION_MAJOR 0) set(EVMJIT_VERSION_MINOR 9) set(EVMJIT_VERSION_PATCH 0) + set(EVMJIT_VERSION_TWEAK 1) endif() set_property(GLOBAL PROPERTY USE_FOLDERS ON) From cf681e379cc880ad162f8efc3f7006d9da33301a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 12 Aug 2015 15:55:23 +0200 Subject: [PATCH 23/41] Update min local stack size correctly. --- evmjit/libevmjit/BasicBlock.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/evmjit/libevmjit/BasicBlock.cpp b/evmjit/libevmjit/BasicBlock.cpp index a60d1ba35..47b590103 100644 --- a/evmjit/libevmjit/BasicBlock.cpp +++ b/evmjit/libevmjit/BasicBlock.cpp @@ -85,7 +85,10 @@ llvm::Value* LocalStack::get(size_t _index) auto& item = m_input[idx]; if (!item) - item = m_global.get(idx); + { + item = m_global.get(idx); // Reach an item from global stack + m_minSize = std::min(m_minSize, -static_cast(idx) - 1); // and remember required stack size + } return item; } From 403b4c03997f614e232cea023f20985ffb21707d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 12 Aug 2015 16:56:49 +0200 Subject: [PATCH 24/41] Remove helper function for getting an item from global stack. --- evmjit/libevmjit/Compiler.cpp | 2 +- evmjit/libevmjit/Stack.cpp | 43 ++--------------------------------- evmjit/libevmjit/Stack.h | 13 ++--------- 3 files changed, 5 insertions(+), 53 deletions(-) diff --git a/evmjit/libevmjit/Compiler.cpp b/evmjit/libevmjit/Compiler.cpp index 30437b6a3..182b5fef8 100644 --- a/evmjit/libevmjit/Compiler.cpp +++ b/evmjit/libevmjit/Compiler.cpp @@ -139,7 +139,7 @@ std::unique_ptr Compiler::compile(code_iterator _begin, code_itera GasMeter gasMeter(m_builder, runtimeManager); Memory memory(runtimeManager, gasMeter); Ext ext(runtimeManager, memory); - Stack stack(m_builder, runtimeManager); + Stack stack(m_builder); runtimeManager.setStack(stack); // Runtime Manager will free stack memory Arith256 arith(m_builder); diff --git a/evmjit/libevmjit/Stack.cpp b/evmjit/libevmjit/Stack.cpp index b83849a92..273aa3855 100644 --- a/evmjit/libevmjit/Stack.cpp +++ b/evmjit/libevmjit/Stack.cpp @@ -16,52 +16,14 @@ namespace eth namespace jit { -Stack::Stack(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager): +Stack::Stack(llvm::IRBuilder<>& _builder): CompilerHelper(_builder), - m_runtimeManager(_runtimeManager), m_stack(_builder, "stack") {} -llvm::Function* Stack::getGetFunc() -{ - auto& func = m_get; - if (!func) - { - llvm::Type* argTypes[] = {Type::Size, Type::Size, Type::BytePtr}; - func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::ExternalLinkage, "stack.require", getModule()); - - auto index = &func->getArgumentList().front(); - index->setName("index"); - auto size = index->getNextNode(); - size->setName("size"); - auto jmpBuf = size->getNextNode(); - jmpBuf->setName("jmpBuf"); - - InsertPointGuard guard{m_builder}; - auto entryBB = llvm::BasicBlock::Create(m_builder.getContext(), {}, func); - auto underflowBB = llvm::BasicBlock::Create(m_builder.getContext(), "Underflow", func); - auto returnBB = llvm::BasicBlock::Create(m_builder.getContext(), "Return", func); - - m_builder.SetInsertPoint(entryBB); - auto underflow = m_builder.CreateICmpUGE(index, size, "underflow"); - m_builder.CreateCondBr(underflow, underflowBB, returnBB); - - m_builder.SetInsertPoint(underflowBB); - m_runtimeManager.abort(jmpBuf); - m_builder.CreateUnreachable(); - - m_builder.SetInsertPoint(returnBB); - m_builder.CreateRetVoid(); - } - return func; -} - llvm::Value* Stack::get(size_t _index) { - createCall(getGetFunc(), {m_builder.getInt64(_index), m_stack.size(), m_runtimeManager.getJmpBuf()}); - auto value = m_stack.get(m_builder.CreateSub(m_stack.size(), m_builder.getInt64(_index + 1))); - //return m_builder.CreateLoad(valuePtr); - return value; + return m_stack.get(m_builder.CreateSub(m_stack.size(), m_builder.getInt64(_index + 1))); } void Stack::set(size_t _index, llvm::Value* _value) @@ -71,7 +33,6 @@ void Stack::set(size_t _index, llvm::Value* _value) void Stack::pop(size_t _count) { - // TODO: We should place stack.require() check and begining of every BB m_stack.pop(m_builder.getInt64(_count)); } diff --git a/evmjit/libevmjit/Stack.h b/evmjit/libevmjit/Stack.h index ad10dae12..72e3d88d2 100644 --- a/evmjit/libevmjit/Stack.h +++ b/evmjit/libevmjit/Stack.h @@ -1,7 +1,5 @@ #pragma once -#include - #include "Array.h" namespace dev @@ -10,12 +8,11 @@ namespace eth { namespace jit { -class RuntimeManager; -class Stack : public CompilerHelper +class Stack: public CompilerHelper { public: - Stack(llvm::IRBuilder<>& builder, RuntimeManager& runtimeManager); + Stack(llvm::IRBuilder<>& builder); llvm::Value* get(size_t _index); void set(size_t _index, llvm::Value* _value); @@ -24,10 +21,6 @@ public: void free() { m_stack.free(); } private: - llvm::Function* getGetFunc(); - - RuntimeManager& m_runtimeManager; - llvm::Function* m_get = nullptr; Array m_stack; }; @@ -35,5 +28,3 @@ private: } } } - - From 7e300407df588e55ca086db779e82f6b0b5d5f96 Mon Sep 17 00:00:00 2001 From: Dimitry Date: Mon, 27 Jul 2015 21:14:55 +0300 Subject: [PATCH 25/41] Nice Error Report --- test/TestHelper.cpp | 26 +++++++++++++++++++++++++- test/TestHelper.h | 8 ++++++++ test/fuzzTesting/fuzzHelper.cpp | 4 ++-- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 4a3de4dc6..094521a68 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -258,7 +258,11 @@ void ImportTest::compareStates(State const& _stateExpect, State const& _statePos #define CHECK(a,b) \ { \ if (_throw == WhenError::Throw) \ - {TBOOST_CHECK_MESSAGE(a,b);}\ + { \ + TBOOST_CHECK(a); \ + if (!a) \ + std::cerr << b << std::endl;\ + } \ else \ {TBOOST_WARN_MESSAGE(a,b);} \ } @@ -773,7 +777,27 @@ Options::Options() } else if (arg == "--fulloutput") fulloutput = true; + else if (arg == "--verbosity" && i + 1 < argc) + { + static std::ostringstream strCout; + std::string depthLevel = std::string{argv[i + 1]}; + if (depthLevel == "0") + { + logVerbosity = Verbosity::None; + std::cout.rdbuf( strCout.rdbuf() ); + std::cerr.rdbuf( strCout.rdbuf() ); + } + else + if (depthLevel == "1") + logVerbosity = Verbosity::NiceReport; + else + logVerbosity = Verbosity::Full; + } } + + //Default option + if (logVerbosity == Verbosity::NiceReport) + g_logVerbosity = -1; //disable cnote but not the cerr } Options const& Options::get() diff --git a/test/TestHelper.h b/test/TestHelper.h index 5f2f8d6d5..a5f50f807 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -218,6 +218,13 @@ void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs) TBOOST_CHECK((_expectedAddrs == _resultAddrs)); }*/ +enum class Verbosity +{ + Full, + NiceReport, + None +}; + class Options { public: @@ -227,6 +234,7 @@ public: std::string statsOutFile; ///< Stats output file. "out" for standard output bool checkState = false;///< Throw error when checking test states bool fulloutput = false;///< Replace large output to just it's length + Verbosity logVerbosity = Verbosity::NiceReport; /// Test selection /// @{ diff --git a/test/fuzzTesting/fuzzHelper.cpp b/test/fuzzTesting/fuzzHelper.cpp index 863c2477c..ebe672fe0 100644 --- a/test/fuzzTesting/fuzzHelper.cpp +++ b/test/fuzzTesting/fuzzHelper.cpp @@ -408,7 +408,7 @@ BOOST_AUTO_TEST_SUITE(RandomCodeTests) BOOST_AUTO_TEST_CASE(rndCode) { std::string code; - std::cerr << "Testing Random Code: "; + std::cout << "Testing Random Code: "; try { code = dev::test::RandomCode::generate(10); @@ -417,7 +417,7 @@ BOOST_AUTO_TEST_CASE(rndCode) { BOOST_ERROR("Exception thrown when generating random code!"); } - std::cerr << code; + std::cout << code; } BOOST_AUTO_TEST_SUITE_END() From fde97e186c1df7dffbb61a839fd60ab5daa75cbd Mon Sep 17 00:00:00 2001 From: Dimitry Date: Tue, 28 Jul 2015 23:32:11 +0300 Subject: [PATCH 26/41] Error logs --- test/TestHelper.cpp | 44 +++++--- test/TestHelper.h | 5 +- test/boostTest.cpp | 57 ++++++++++ test/fuzzTesting/fuzzHelper.cpp | 5 +- test/libdevcore/rlp.cpp | 25 +++-- test/libdevcrypto/AES.cpp | 14 +-- test/libdevcrypto/hexPrefix.cpp | 2 +- test/libdevcrypto/trie.cpp | 100 +++++++++--------- test/libethcore/dagger.cpp | 2 +- test/libethereum/genesis.cpp | 4 +- test/libethereum/state.cpp | 22 ++-- test/libethereum/stateOriginal.cpp | 2 +- test/libethereum/transactionTests.cpp | 40 +++---- test/libevm/vm.cpp | 15 +-- test/libevm/vm.h | 2 +- test/libp2p/capability.cpp | 4 +- test/libp2p/peer.cpp | 10 +- test/libsolidity/solidityExecutionFramework.h | 4 +- test/libwhisper/bloomFilter.cpp | 12 ++- test/libwhisper/whisperDB.cpp | 20 +++- test/libwhisper/whisperMessage.cpp | 7 +- test/libwhisper/whisperTopic.cpp | 8 +- 22 files changed, 258 insertions(+), 146 deletions(-) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 094521a68..80b4214cf 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -253,15 +253,15 @@ void ImportTest::importTransaction(json_spirit::mObject const& o_tr) importTransaction(o_tr, m_transaction); } -void ImportTest::compareStates(State const& _stateExpect, State const& _statePost, AccountMaskMap const _expectedStateOptions, WhenError _throw) +int ImportTest::compareStates(State const& _stateExpect, State const& _statePost, AccountMaskMap const _expectedStateOptions, WhenError _throw) { #define CHECK(a,b) \ { \ if (_throw == WhenError::Throw) \ { \ - TBOOST_CHECK(a); \ + TBOOST_CHECK_MESSAGE(a, b); \ if (!a) \ - std::cerr << b << std::endl;\ + return 1; \ } \ else \ {TBOOST_WARN_MESSAGE(a,b);} \ @@ -313,20 +313,26 @@ void ImportTest::compareStates(State const& _stateExpect, State const& _statePos "Check State: " << a.first << ": incorrect code '" << toHex(_statePost.code(a.first)) << "', expected '" << toHex(_stateExpect.code(a.first)) << "'"); } } + return 0; } -void ImportTest::exportTest(bytes const& _output) +int ImportTest::exportTest(bytes const& _output) { - // export output - - m_testObject["out"] = (_output.size() > 4096 && !Options::get().fulloutput) ? "#" + toString(_output.size()) : toHex(_output, 2, HexPrefix::Add); + int err = 0; + // export output + m_TestObject["out"] = (_output.size() > 4096 && !Options::get().fulloutput) ? "#" + toString(_output.size()) : toHex(_output, 2, HexPrefix::Add); // compare expected output with post output if (m_testObject.count("expectOut") > 0) { std::string warning = "Check State: Error! Unexpected output: " + m_testObject["out"].get_str() + " Expected: " + m_testObject["expectOut"].get_str(); if (Options::get().checkState) - {TBOOST_CHECK_MESSAGE((m_testObject["out"].get_str() == m_testObject["expectOut"].get_str()), warning);} + { + bool statement = (m_testObject["out"].get_str() == m_testObject["expectOut"].get_str()); + TBOOST_CHECK_MESSAGE(statement, warning); + if (!statement) + err = 1; + } else TBOOST_WARN_MESSAGE((m_testObject["out"].get_str() == m_testObject["expectOut"].get_str()), warning); @@ -354,6 +360,7 @@ void ImportTest::exportTest(bytes const& _output) m_testObject["pre"] = fillJsonWithState(m_statePre); m_testObject["env"] = makeAllFieldsHex(m_testObject["env"].get_obj()); m_testObject["transaction"] = makeAllFieldsHex(m_testObject["transaction"].get_obj()); + return err; } json_spirit::mObject fillJsonWithTransaction(Transaction _txn) @@ -570,7 +577,10 @@ void userDefinedTest(std::function doTests) auto& filename = Options::get().singleTestFile; auto& testname = Options::get().singleTestName; - VerbosityHolder sentinel(12); + + if (g_logVerbosity != -1) + VerbosityHolder sentinel(12); + try { cnote << "Testing user defined test: " << filename; @@ -635,7 +645,7 @@ void executeTests(const string& _name, const string& _testPathAppendix, const bo try { - std::cout << "TEST " << _name << ":\n"; + cnote << "TEST " << _name << ":"; json_spirit::mValue v; string s = asString(dev::contents(testPath + "/" + _name + ".json")); TBOOST_REQUIRE_MESSAGE((s.length() > 0), "Contents of " + testPath + "/" + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); @@ -779,16 +789,16 @@ Options::Options() fulloutput = true; else if (arg == "--verbosity" && i + 1 < argc) { - static std::ostringstream strCout; - std::string depthLevel = std::string{argv[i + 1]}; - if (depthLevel == "0") + static std::ostringstream strCout; //static string to redirect logs to + std::string indentLevel = std::string{argv[i + 1]}; + if (indentLevel == "0") { logVerbosity = Verbosity::None; - std::cout.rdbuf( strCout.rdbuf() ); - std::cerr.rdbuf( strCout.rdbuf() ); + std::cout.rdbuf(strCout.rdbuf()); + std::cerr.rdbuf(strCout.rdbuf()); } else - if (depthLevel == "1") + if (indentLevel == "1") logVerbosity = Verbosity::NiceReport; else logVerbosity = Verbosity::Full; @@ -797,7 +807,7 @@ Options::Options() //Default option if (logVerbosity == Verbosity::NiceReport) - g_logVerbosity = -1; //disable cnote but not the cerr + g_logVerbosity = -1; //disable cnote but leave cerr and cout } Options const& Options::get() diff --git a/test/TestHelper.h b/test/TestHelper.h index a5f50f807..e5cf13233 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -22,7 +22,6 @@ #pragma once #include - #include #include @@ -143,8 +142,8 @@ public: static json_spirit::mObject& makeAllFieldsHex(json_spirit::mObject& _o); bytes executeTest(); - void exportTest(bytes const& _output); - static void compareStates(eth::State const& _stateExpect, eth::State const& _statePost, eth::AccountMaskMap const _expectedStateOptions = eth::AccountMaskMap(), WhenError _throw = WhenError::Throw); + int exportTest(bytes const& _output); + static int compareStates(eth::State const& _stateExpect, eth::State const& _statePost, eth::AccountMaskMap const _expectedStateOptions = eth::AccountMaskMap(), WhenError _throw = WhenError::Throw); eth::State m_statePre; eth::State m_statePost; diff --git a/test/boostTest.cpp b/test/boostTest.cpp index 1523a7a11..af546c3a3 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -24,5 +24,62 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #define BOOST_DISABLE_WIN32 //disables SEH warning +#define BOOST_TEST_NO_MAIN #include #pragma GCC diagnostic pop + +#include +using namespace boost::unit_test; + +//Custom Boost Initialization +test_suite* init_func( int argc, char* argv[] ) +{ + if (argc == 0) + argv[1]=(char*)"a"; + + dev::test::Options::get(); + + return 0; +} + +//Custom Boost Unit Test Main +int main( int argc, char* argv[] ) +{ + try { + framework::init( init_func, argc, argv ); + + if( !runtime_config::test_to_run().is_empty() ) { + test_case_filter filter( runtime_config::test_to_run() ); + + traverse_test_tree( framework::master_test_suite().p_id, filter ); + } + + framework::run(); + + results_reporter::make_report(); + + return runtime_config::no_result_code() + ? boost::exit_success + : results_collector.results( framework::master_test_suite().p_id ).result_code(); + } + catch( framework::nothing_to_test const& ) { + return boost::exit_success; + } + catch( framework::internal_error const& ex ) { + results_reporter::get_stream() << "Boost.Test framework internal error: " << ex.what() << std::endl; + + return boost::exit_exception_failure; + } + catch( framework::setup_error const& ex ) { + results_reporter::get_stream() << "Test setup error: " << ex.what() << std::endl; + + return boost::exit_exception_failure; + } + catch( ... ) { + results_reporter::get_stream() << "Boost.Test framework internal error: unknown reason" << std::endl; + + return boost::exit_exception_failure; + } + + return 0; +} diff --git a/test/fuzzTesting/fuzzHelper.cpp b/test/fuzzTesting/fuzzHelper.cpp index ebe672fe0..63fad5a46 100644 --- a/test/fuzzTesting/fuzzHelper.cpp +++ b/test/fuzzTesting/fuzzHelper.cpp @@ -402,13 +402,12 @@ void RandomCodeOptions::setWeights() opCodeProbability = boostDescreteDistrib(weights); } - BOOST_AUTO_TEST_SUITE(RandomCodeTests) BOOST_AUTO_TEST_CASE(rndCode) { std::string code; - std::cout << "Testing Random Code: "; + cnote << "Testing Random Code: "; try { code = dev::test::RandomCode::generate(10); @@ -417,7 +416,7 @@ BOOST_AUTO_TEST_CASE(rndCode) { BOOST_ERROR("Exception thrown when generating random code!"); } - std::cout << code; + cnote << code; } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libdevcore/rlp.cpp b/test/libdevcore/rlp.cpp index e64621053..d351bb41a 100644 --- a/test/libdevcore/rlp.cpp +++ b/test/libdevcore/rlp.cpp @@ -52,6 +52,7 @@ namespace dev void doRlpTests(json_spirit::mValue& v, bool _fillin) { + string testname; for (auto& i: v.get_obj()) { js::mObject& o = i.second.get_obj(); @@ -61,9 +62,11 @@ namespace dev continue; } - cout << " " << i.first << endl; - TBOOST_REQUIRE((o.count("out") > 0)); - TBOOST_REQUIRE((!o["out"].is_null())); + cnote << " " << i.first; + testname = "(" + i.first + ") "; + + TBOOST_REQUIRE_MESSAGE((o.count("out") > 0), testname + "out not set!"); + TBOOST_REQUIRE_MESSAGE((!o["out"].is_null()), testname + "out is set to null!"); if (_fillin) { @@ -88,7 +91,7 @@ namespace dev else { //Check Encode - TBOOST_REQUIRE((o.count("in") > 0)); + TBOOST_REQUIRE_MESSAGE((o.count("in") > 0), testname + "in not set!"); RlpType rlpType = RlpType::Test; if (o["in"].type() == js::str_type) { @@ -112,7 +115,7 @@ namespace dev msg << " But Computed: " << computedText; TBOOST_CHECK_MESSAGE( (expectedText == computedText), - msg.str() + testname + msg.str() ); } @@ -155,11 +158,11 @@ namespace dev //Check that there was an exception as input is INVALID if (rlpType == RlpType::Invalid && !was_exception) - TBOOST_ERROR("Expected RLP Exception as rlp should be invalid!"); + TBOOST_ERROR(testname + "Expected RLP Exception as rlp should be invalid!"); //input is VALID check that there was no exceptions if (was_exception) - TBOOST_ERROR("Unexpected RLP Exception!"); + TBOOST_ERROR(testname + "Unexpected RLP Exception!"); } } } @@ -256,11 +259,11 @@ BOOST_AUTO_TEST_CASE(EmptyArrayList) } catch (Exception const& _e) { - TBOOST_ERROR("Failed test with Exception: " << _e.what()); + TBOOST_ERROR("(EmptyArrayList) Failed test with Exception: " << _e.what()); } catch (exception const& _e) { - TBOOST_ERROR("Failed test with Exception: " << _e.what()); + TBOOST_ERROR("(EmptyArrayList) Failed test with Exception: " << _e.what()); } } @@ -302,11 +305,11 @@ BOOST_AUTO_TEST_CASE(rlpRandom) catch (Exception const& _e) { - TBOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); + TBOOST_ERROR(path.filename().string() + "Failed test with Exception: " << diagnostic_information(_e)); } catch (std::exception const& _e) { - TBOOST_ERROR("Failed test with Exception: " << _e.what()); + TBOOST_ERROR(path.filename().string() + "Failed test with Exception: " << _e.what()); } } } diff --git a/test/libdevcrypto/AES.cpp b/test/libdevcrypto/AES.cpp index 0617033aa..3991a7471 100644 --- a/test/libdevcrypto/AES.cpp +++ b/test/libdevcrypto/AES.cpp @@ -25,6 +25,7 @@ #include #include #include +#include using namespace std; using namespace dev; @@ -33,7 +34,7 @@ BOOST_AUTO_TEST_SUITE(AES) BOOST_AUTO_TEST_CASE(AesDecrypt) { - cout << "AesDecrypt" << endl; + cnote << "AesDecrypt"; bytes seed = fromHex("2dbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); KeyPair kp(sha3Secure(aesDecrypt(&seed, "test"))); BOOST_CHECK(Address("07746f871de684297923f933279555dda418f8a2") == kp.address()); @@ -41,7 +42,7 @@ BOOST_AUTO_TEST_CASE(AesDecrypt) BOOST_AUTO_TEST_CASE(AesDecryptWrongSeed) { - cout << "AesDecryptWrongSeed" << endl; + cnote << "AesDecryptWrongSeed"; bytes seed = fromHex("badaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); KeyPair kp(sha3Secure(aesDecrypt(&seed, "test"))); BOOST_CHECK(Address("07746f871de684297923f933279555dda418f8a2") != kp.address()); @@ -49,7 +50,7 @@ BOOST_AUTO_TEST_CASE(AesDecryptWrongSeed) BOOST_AUTO_TEST_CASE(AesDecryptWrongPassword) { - cout << "AesDecryptWrongPassword" << endl; + cnote << "AesDecryptWrongPassword"; bytes seed = fromHex("2dbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); KeyPair kp(sha3Secure(aesDecrypt(&seed, "badtest"))); BOOST_CHECK(Address("07746f871de684297923f933279555dda418f8a2") != kp.address()); @@ -57,24 +58,23 @@ BOOST_AUTO_TEST_CASE(AesDecryptWrongPassword) BOOST_AUTO_TEST_CASE(AesDecryptFailInvalidSeed) { - cout << "AesDecryptFailInvalidSeed" << endl; + cnote << "AesDecryptFailInvalidSeed"; bytes seed = fromHex("xdbaead416c20cfd00c2fc9f1788ff9f965a2000799c96a624767cb0e1e90d2d7191efdd92349226742fdc73d1d87e2d597536c4641098b9a89836c94f58a2ab4c525c27c4cb848b3e22ea245b2bc5c8c7beaa900b0c479253fc96fce7ffc621"); BOOST_CHECK(bytes() == aesDecrypt(&seed, "test")); } BOOST_AUTO_TEST_CASE(AesDecryptFailInvalidSeedSize) { - cout << "AesDecryptFailInvalidSeedSize" << endl; + cnote << "AesDecryptFailInvalidSeedSize"; bytes seed = fromHex("000102030405060708090a0b0c0d0e0f"); BOOST_CHECK(bytes() == aesDecrypt(&seed, "test")); } BOOST_AUTO_TEST_CASE(AesDecryptFailInvalidSeed2) { - cout << "AesDecryptFailInvalidSeed2" << endl; + cnote << "AesDecryptFailInvalidSeed2"; bytes seed = fromHex("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"); BOOST_CHECK(bytes() == aesDecrypt(&seed, "test")); } BOOST_AUTO_TEST_SUITE_END() - diff --git a/test/libdevcrypto/hexPrefix.cpp b/test/libdevcrypto/hexPrefix.cpp index 4d89ec594..6c87387cf 100644 --- a/test/libdevcrypto/hexPrefix.cpp +++ b/test/libdevcrypto/hexPrefix.cpp @@ -29,7 +29,7 @@ #include #include #include -#include "../TestHelper.h" +#include using namespace std; using namespace dev; diff --git a/test/libdevcrypto/trie.cpp b/test/libdevcrypto/trie.cpp index be88c7cee..23fec311b 100644 --- a/test/libdevcrypto/trie.cpp +++ b/test/libdevcrypto/trie.cpp @@ -27,7 +27,7 @@ #include #include #include "MemTrie.h" -#include "../TestHelper.h" +#include using namespace std; using namespace dev; @@ -315,35 +315,35 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) MemoryDB m; GenericTrieDB t(&m); t.init(); // initialise as empty tree. - cout << t; - cout << m; - cout << t.root() << endl; - cout << stringMapHash256(StringMap()) << endl; + cnote << t; + cnote << m; + cnote << t.root(); + cnote << stringMapHash256(StringMap()); t.insert(string("tesz"), string("test")); - cout << t; - cout << m; - cout << t.root() << endl; - cout << stringMapHash256({{"test", "test"}}) << endl; + cnote << t; + cnote << m; + cnote << t.root(); + cnote << stringMapHash256({{"test", "test"}}); t.insert(string("tesa"), string("testy")); - cout << t; - cout << m; - cout << t.root() << endl; - cout << stringMapHash256({{"test", "test"}, {"te", "testy"}}) << endl; - cout << t.at(string("test")) << endl; - cout << t.at(string("te")) << endl; - cout << t.at(string("t")) << endl; + cnote << t; + cnote << m; + cnote << t.root(); + cnote << stringMapHash256({{"test", "test"}, {"te", "testy"}}); + cnote << t.at(string("test")); + cnote << t.at(string("te")); + cnote << t.at(string("t")); t.remove(string("te")); - cout << m; - cout << t.root() << endl; - cout << stringMapHash256({{"test", "test"}}) << endl; + cnote << m; + cnote << t.root(); + cnote << stringMapHash256({{"test", "test"}}); t.remove(string("test")); - cout << m; - cout << t.root() << endl; - cout << stringMapHash256(StringMap()) << endl; + cnote << m; + cnote << t.root(); + cnote << stringMapHash256(StringMap()); } { MemoryDB m; @@ -351,37 +351,37 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) t.init(); // initialise as empty tree. t.insert(string("a"), string("A")); t.insert(string("b"), string("B")); - cout << t; - cout << m; - cout << t.root() << endl; - cout << stringMapHash256({{"b", "B"}, {"a", "A"}}) << endl; + cnote << t; + cnote << m; + cnote << t.root(); + cnote << stringMapHash256({{"b", "B"}, {"a", "A"}}); bytes r(stringMapRlp256({{"b", "B"}, {"a", "A"}})); - cout << RLP(r) << endl; + cnote << RLP(r); } { MemTrie t; t.insert("dog", "puppy"); - cout << hex << t.hash256() << endl; + cnote << hex << t.hash256(); bytes r(t.rlp()); - cout << RLP(r) << endl; + cnote << RLP(r); } { MemTrie t; t.insert("bed", "d"); t.insert("be", "e"); - cout << hex << t.hash256() << endl; + cnote << hex << t.hash256(); bytes r(t.rlp()); - cout << RLP(r) << endl; + cnote << RLP(r); } { - cout << hex << stringMapHash256({{"dog", "puppy"}, {"doe", "reindeer"}}) << endl; + cnote << hex << stringMapHash256({{"dog", "puppy"}, {"doe", "reindeer"}}); MemTrie t; t.insert("dog", "puppy"); t.insert("doe", "reindeer"); - cout << hex << t.hash256() << endl; + cnote << hex << t.hash256(); bytes r(t.rlp()); - cout << RLP(r) << endl; - cout << toHex(t.rlp()) << endl; + cnote << RLP(r); + cnote << toHex(t.rlp()); } { MemoryDB m; @@ -397,12 +397,12 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) t.insert(a, b); s[a] = b; - cout << endl << "-------------------------------" << endl; - cout << a << " -> " << b << endl; - cout << d; - cout << m; - cout << d.root() << endl; - cout << stringMapHash256(s) << endl; + cnote << "/n-------------------------------"; + cnote << a << " -> " << b; + cnote << d; + cnote << m; + cnote << d.root(); + cnote << stringMapHash256(s); BOOST_REQUIRE(d.check(true)); BOOST_REQUIRE_EQUAL(t.hash256(), stringMapHash256(s)); @@ -421,12 +421,12 @@ BOOST_AUTO_TEST_CASE(moreTrieTests) t.remove(a); d.remove(string(a)); - /*cout << endl << "-------------------------------" << endl; - cout << "X " << a << endl; - cout << d; - cout << m; - cout << d.root() << endl; - cout << hash256(s) << endl;*/ + /*cnote << endl << "-------------------------------"; + cnote << "X " << a; + cnote << d; + cnote << m; + cnote << d.root(); + cnote << hash256(s);*/ BOOST_REQUIRE(d.check(true)); BOOST_REQUIRE(t.at(a).empty()); @@ -559,9 +559,11 @@ BOOST_AUTO_TEST_CASE(trieStess) // for (auto i: dm2.get()) // cwarn << i.first << ": " << RLP(i.second); d2.debugStructure(cerr); - g_logVerbosity = 99; + if (g_logVerbosity != -1) + g_logVerbosity = 99; d2.remove(k); - g_logVerbosity = 4; + if (g_logVerbosity != -1) + g_logVerbosity = 4; cwarn << "Good?" << d2.root(); } diff --git a/test/libethcore/dagger.cpp b/test/libethcore/dagger.cpp index 0473a0136..9841b1b4b 100644 --- a/test/libethcore/dagger.cpp +++ b/test/libethcore/dagger.cpp @@ -25,7 +25,7 @@ #include #include #include -#include "../TestHelper.h" +#include using namespace std; using namespace dev; diff --git a/test/libethereum/genesis.cpp b/test/libethereum/genesis.cpp index 8d4b2878f..aa0825c42 100644 --- a/test/libethereum/genesis.cpp +++ b/test/libethereum/genesis.cpp @@ -21,11 +21,13 @@ */ #include +#include + #include #include "../JsonSpiritHeaders.h" #include #include -#include "../TestHelper.h" +#include using namespace std; using namespace dev; diff --git a/test/libethereum/state.cpp b/test/libethereum/state.cpp index 4c9d998b2..30c0ccff0 100644 --- a/test/libethereum/state.cpp +++ b/test/libethereum/state.cpp @@ -41,6 +41,7 @@ namespace dev { namespace test { void doStateTests(json_spirit::mValue& v, bool _fillin) { + string testname; for (auto& i: v.get_obj()) { mObject& o = i.second.get_obj(); @@ -50,10 +51,12 @@ void doStateTests(json_spirit::mValue& v, bool _fillin) continue; } - std::cout << " " << i.first << std::endl; - TBOOST_REQUIRE((o.count("env") > 0)); - TBOOST_REQUIRE((o.count("pre") > 0)); - TBOOST_REQUIRE((o.count("transaction") > 0)); + cnote << i.first; + testname = "(" + i.first + ") "; + + TBOOST_REQUIRE_MESSAGE((o.count("env") > 0), testname + "env not set!"); + TBOOST_REQUIRE_MESSAGE((o.count("pre") > 0), testname + "pre not set!"); + TBOOST_REQUIRE_MESSAGE((o.count("transaction") > 0), testname + "transaction not set!"); ImportTest importer(o, _fillin); const State importedStatePost = importer.m_statePost; @@ -66,9 +69,10 @@ void doStateTests(json_spirit::mValue& v, bool _fillin) if (_fillin) { #if ETH_FATDB - importer.exportTest(output); + if (importer.exportTest(output)) + cerr << testname << endl; #else - BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("You can not fill tests when FATDB is switched off")); + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment(testname + "You can not fill tests when FATDB is switched off")); #endif } else @@ -86,7 +90,7 @@ void doStateTests(json_spirit::mValue& v, bool _fillin) #if ETH_FATDB ImportTest::compareStates(importer.m_statePost, importedStatePost); #endif - TBOOST_CHECK_MESSAGE((importer.m_statePost.rootHash() == h256(o["postStateRoot"].get_str())), "wrong post state root"); + TBOOST_CHECK_MESSAGE((importer.m_statePost.rootHash() == h256(o["postStateRoot"].get_str())), testname + "wrong post state root"); } } } @@ -237,11 +241,11 @@ BOOST_AUTO_TEST_CASE(stRandom) } catch (Exception const& _e) { - BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); + BOOST_ERROR(path.filename().string() + "Failed test with Exception: " << diagnostic_information(_e)); } catch (std::exception const& _e) { - BOOST_ERROR("Failed test with Exception: " << _e.what()); + BOOST_ERROR(path.filename().string() + "Failed test with Exception: " << _e.what()); } } } diff --git a/test/libethereum/stateOriginal.cpp b/test/libethereum/stateOriginal.cpp index 21b332762..8ed3b228d 100644 --- a/test/libethereum/stateOriginal.cpp +++ b/test/libethereum/stateOriginal.cpp @@ -20,6 +20,7 @@ * State test functions. */ +#include #include #include #include @@ -27,7 +28,6 @@ #include #include #include -#include using namespace std; using namespace dev; diff --git a/test/libethereum/transactionTests.cpp b/test/libethereum/transactionTests.cpp index f6bde061a..4131d7454 100644 --- a/test/libethereum/transactionTests.cpp +++ b/test/libethereum/transactionTests.cpp @@ -32,6 +32,7 @@ namespace dev { namespace test { void doTransactionTests(json_spirit::mValue& _v, bool _fillin) { + string testname; for (auto& i: _v.get_obj()) { mObject& o = i.second.get_obj(); @@ -41,7 +42,8 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) continue; } - cerr << i.first << endl; + testname = "(" + i.first ") "; + cnote << testname; if (_fillin) { TBOOST_REQUIRE((o.count("transaction") > 0)); @@ -55,7 +57,7 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) { Transaction txFromFields(rlpStream.out(), CheckTransaction::Everything); if (!txFromFields.signature().isValid()) - BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") ); + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment(testname + "transaction from RLP signature is invalid") ); o["sender"] = toString(txFromFields.sender()); o["transaction"] = ImportTest::makeAllFieldsHex(tObj); @@ -69,9 +71,9 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) { bool expectInValid = (o["expect"].get_str() == "invalid"); if (Options::get().checkState) - {TBOOST_CHECK_MESSAGE(expectInValid, "Check state: Transaction '" << i.first << "' is expected to be valid!");} + {TBOOST_CHECK_MESSAGE(expectInValid, testname + "Check state: Transaction '" << i.first << "' is expected to be valid!");} else - {TBOOST_WARN_MESSAGE(expectInValid, "Check state: Transaction '" << i.first << "' is expected to be valid!");} + {TBOOST_WARN_MESSAGE(expectInValid, testname + "Check state: Transaction '" << i.first << "' is expected to be valid!");} o.erase(o.find("expect")); } @@ -82,9 +84,9 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) { bool expectValid = (o["expect"].get_str() == "valid"); if (Options::get().checkState) - {TBOOST_CHECK_MESSAGE(expectValid, "Check state: Transaction '" << i.first << "' is expected to be invalid!");} + {TBOOST_CHECK_MESSAGE(expectValid, testname + "Check state: Transaction '" << i.first << "' is expected to be invalid!");} else - {TBOOST_WARN_MESSAGE(expectValid, "Check state: Transaction '" << i.first << "' is expected to be invalid!");} + {TBOOST_WARN_MESSAGE(expectValid, testname + "Check state: Transaction '" << i.first << "' is expected to be invalid!");} o.erase(o.find("expect")); } @@ -99,39 +101,39 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) RLP rlp(stream); txFromRlp = Transaction(rlp.data(), CheckTransaction::Everything); if (!txFromRlp.signature().isValid()) - BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") ); + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment(testname + "transaction from RLP signature is invalid") ); } catch(Exception const& _e) { cnote << i.first; cnote << "Transaction Exception: " << diagnostic_information(_e); - TBOOST_CHECK_MESSAGE((o.count("transaction") == 0), "A transaction object should not be defined because the RLP is invalid!"); + TBOOST_CHECK_MESSAGE((o.count("transaction") == 0), testname + "A transaction object should not be defined because the RLP is invalid!"); continue; } catch(...) { - TBOOST_CHECK_MESSAGE((o.count("transaction") == 0), "A transaction object should not be defined because the RLP is invalid!"); + TBOOST_CHECK_MESSAGE((o.count("transaction") == 0), testname + "A transaction object should not be defined because the RLP is invalid!"); continue; } - TBOOST_REQUIRE((o.count("transaction") > 0)); + TBOOST_REQUIRE_MESSAGE((o.count("transaction") > 0), testname + "Expected a valid transaction!"); mObject tObj = o["transaction"].get_obj(); Transaction txFromFields(createRLPStreamFromTransactionFields(tObj).out(), CheckTransaction::Everything); //Check the fields restored from RLP to original fields - TBOOST_CHECK_MESSAGE((txFromFields.data() == txFromRlp.data()), "Data in given RLP not matching the Transaction data!"); - TBOOST_CHECK_MESSAGE((txFromFields.value() == txFromRlp.value()), "Value in given RLP not matching the Transaction value!"); - TBOOST_CHECK_MESSAGE((txFromFields.gasPrice() == txFromRlp.gasPrice()), "GasPrice in given RLP not matching the Transaction gasPrice!"); - TBOOST_CHECK_MESSAGE((txFromFields.gas() == txFromRlp.gas()),"Gas in given RLP not matching the Transaction gas!"); - TBOOST_CHECK_MESSAGE((txFromFields.nonce() == txFromRlp.nonce()),"Nonce in given RLP not matching the Transaction nonce!"); - TBOOST_CHECK_MESSAGE((txFromFields.receiveAddress() == txFromRlp.receiveAddress()), "Receive address in given RLP not matching the Transaction 'to' address!"); - TBOOST_CHECK_MESSAGE((txFromFields.sender() == txFromRlp.sender()), "Transaction sender address in given RLP not matching the Transaction 'vrs' signature!"); - TBOOST_CHECK_MESSAGE((txFromFields == txFromRlp), "However, txFromFields != txFromRlp!"); + TBOOST_CHECK_MESSAGE((txFromFields.data() == txFromRlp.data()), testname + "Data in given RLP not matching the Transaction data!"); + TBOOST_CHECK_MESSAGE((txFromFields.value() == txFromRlp.value()), testname + "Value in given RLP not matching the Transaction value!"); + TBOOST_CHECK_MESSAGE((txFromFields.gasPrice() == txFromRlp.gasPrice()), testname + "GasPrice in given RLP not matching the Transaction gasPrice!"); + TBOOST_CHECK_MESSAGE((txFromFields.gas() == txFromRlp.gas()), testname + "Gas in given RLP not matching the Transaction gas!"); + TBOOST_CHECK_MESSAGE((txFromFields.nonce() == txFromRlp.nonce()), testname + "Nonce in given RLP not matching the Transaction nonce!"); + TBOOST_CHECK_MESSAGE((txFromFields.receiveAddress() == txFromRlp.receiveAddress()), testname + "Receive address in given RLP not matching the Transaction 'to' address!"); + TBOOST_CHECK_MESSAGE((txFromFields.sender() == txFromRlp.sender()), testname + "Transaction sender address in given RLP not matching the Transaction 'vrs' signature!"); + TBOOST_CHECK_MESSAGE((txFromFields == txFromRlp), testname + "However, txFromFields != txFromRlp!"); TBOOST_REQUIRE ((o.count("sender") > 0)); Address addressReaded = Address(o["sender"].get_str()); - TBOOST_CHECK_MESSAGE((txFromFields.sender() == addressReaded || txFromRlp.sender() == addressReaded), "Signature address of sender does not match given sender address!"); + TBOOST_CHECK_MESSAGE((txFromFields.sender() == addressReaded || txFromRlp.sender() == addressReaded), testname + "Signature address of sender does not match given sender address!"); } }//for }//doTransactionTests diff --git a/test/libevm/vm.cpp b/test/libevm/vm.cpp index 44e0ebe84..ec28f0005 100644 --- a/test/libevm/vm.cpp +++ b/test/libevm/vm.cpp @@ -296,6 +296,7 @@ namespace dev { namespace test { void doVMTests(json_spirit::mValue& v, bool _fillin) { + string testname; for (auto& i: v.get_obj()) { mObject& o = i.second.get_obj(); @@ -305,10 +306,12 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) continue; } - std::cout << " " << i.first << "\n"; - TBOOST_REQUIRE((o.count("env") > 0)); - TBOOST_REQUIRE((o.count("pre") > 0)); - TBOOST_REQUIRE((o.count("exec") > 0)); + cnote << i.first; + testname = "(" + i.first + ") "; + + TBOOST_REQUIRE_MESSAGE((o.count("env") > 0), testname + "env not set!"); + TBOOST_REQUIRE_MESSAGE((o.count("pre") > 0), testname + "pre not set!"); + TBOOST_REQUIRE_MESSAGE((o.count("exec") > 0), testname + "exec not set!"); FakeExtVM fev(eth::EnvInfo{}); fev.importEnv(o["env"].get_obj()); @@ -338,7 +341,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) } catch (VMException const&) { - std::cout << " Safe VM Exception\n"; + cnote << " Safe VM Exception\n"; vmExceptionOccured = true; } catch (Exception const& _e) @@ -535,7 +538,7 @@ BOOST_AUTO_TEST_CASE(vmRandom) { try { - std::cout << "TEST " << path.filename() << "\n"; + cnote << "TEST " << path.filename(); json_spirit::mValue v; string s = asString(dev::contents(path.string())); BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + path.string() + " is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); diff --git a/test/libevm/vm.h b/test/libevm/vm.h index c41ebf5dc..c51afbd02 100644 --- a/test/libevm/vm.h +++ b/test/libevm/vm.h @@ -26,6 +26,7 @@ along with cpp-ethereum. If not, see . #include #include +#include #include #include @@ -38,7 +39,6 @@ along with cpp-ethereum. If not, see . #include #include #include -#include namespace dev { namespace test { diff --git a/test/libp2p/capability.cpp b/test/libp2p/capability.cpp index e60f7f131..fffc43c40 100644 --- a/test/libp2p/capability.cpp +++ b/test/libp2p/capability.cpp @@ -102,7 +102,9 @@ BOOST_AUTO_TEST_CASE(capability) if (test::Options::get().nonetwork) return; - VerbosityHolder verbosityHolder(10); + if (g_logVerbosity != -1) + VerbosityHolder verbosityHolder(10); + cnote << "Testing Capability..."; const char* const localhost = "127.0.0.1"; diff --git a/test/libp2p/peer.cpp b/test/libp2p/peer.cpp index 43308b450..570c443ec 100644 --- a/test/libp2p/peer.cpp +++ b/test/libp2p/peer.cpp @@ -43,7 +43,9 @@ BOOST_AUTO_TEST_CASE(host) if (test::Options::get().nonetwork) return; - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + NetworkPreferences host1prefs("127.0.0.1", 30321, false); NetworkPreferences host2prefs("127.0.0.1", 30322, false); Host host1("Test", host1prefs); @@ -88,7 +90,8 @@ BOOST_AUTO_TEST_CASE(saveNodes) if (test::Options::get().nonetwork) return; - VerbosityHolder reduceVerbosity(2); + if (g_logVerbosity != -1) + VerbosityHolder reduceVerbosity(2); std::list hosts; unsigned const c_step = 10; @@ -152,7 +155,8 @@ BOOST_AUTO_TEST_CASE(requirePeer) if (test::Options::get().nonetwork) return; - VerbosityHolder temporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder reduceVerbosity(10); unsigned const step = 10; const char* const localhost = "127.0.0.1"; diff --git a/test/libsolidity/solidityExecutionFramework.h b/test/libsolidity/solidityExecutionFramework.h index 98241b2ff..aac033b50 100644 --- a/test/libsolidity/solidityExecutionFramework.h +++ b/test/libsolidity/solidityExecutionFramework.h @@ -44,7 +44,9 @@ class ExecutionFramework public: ExecutionFramework() { - g_logVerbosity = 0; + if (g_logVerbosity != -1) + g_logVerbosity = 0; + m_state.resetCurrent(); } bytes const& compileAndRunWithoutCheck( diff --git a/test/libwhisper/bloomFilter.cpp b/test/libwhisper/bloomFilter.cpp index d7d4bd849..6516f81b1 100644 --- a/test/libwhisper/bloomFilter.cpp +++ b/test/libwhisper/bloomFilter.cpp @@ -106,7 +106,9 @@ BOOST_AUTO_TEST_SUITE(bloomFilter) BOOST_AUTO_TEST_CASE(falsePositiveRate) { - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing Bloom Filter False Positive Rate..."; TopicBloomFilterTest f; @@ -124,7 +126,9 @@ BOOST_AUTO_TEST_CASE(falsePositiveRate) BOOST_AUTO_TEST_CASE(bloomFilterRandom) { - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing Bloom Filter matching..."; TopicBloomFilterShort f; @@ -150,7 +154,9 @@ BOOST_AUTO_TEST_CASE(bloomFilterRandom) BOOST_AUTO_TEST_CASE(bloomFilterRaw) { - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing Raw Bloom matching..."; TopicBloomFilterShort f; diff --git a/test/libwhisper/whisperDB.cpp b/test/libwhisper/whisperDB.cpp index 3d7b09915..bc56c4b4c 100644 --- a/test/libwhisper/whisperDB.cpp +++ b/test/libwhisper/whisperDB.cpp @@ -41,7 +41,9 @@ BOOST_FIXTURE_TEST_SUITE(whisperDB, P2PFixture) BOOST_AUTO_TEST_CASE(basic) { - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing Whisper DB..."; string s; @@ -86,7 +88,9 @@ BOOST_AUTO_TEST_CASE(basic) BOOST_AUTO_TEST_CASE(persistence) { - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing persistence of Whisper DB..."; string s; @@ -135,7 +139,9 @@ BOOST_AUTO_TEST_CASE(messages) return; cnote << "Testing load/save Whisper messages..."; - VerbosityHolder setTemporaryLevel(2); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(2); + unsigned const TestSize = 3; map m1; map preexisting; @@ -193,7 +199,9 @@ BOOST_AUTO_TEST_CASE(corruptedData) return; cnote << "Testing corrupted data..."; - VerbosityHolder setTemporaryLevel(2); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(2); + map m; h256 x = h256::random(); @@ -222,7 +230,9 @@ BOOST_AUTO_TEST_CASE(filters) return; cnote << "Testing filters saving..."; - VerbosityHolder setTemporaryLevel(2); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(2); + h256 persistID(0xC0FFEE); { diff --git a/test/libwhisper/whisperMessage.cpp b/test/libwhisper/whisperMessage.cpp index f0c0aedc9..662653540 100644 --- a/test/libwhisper/whisperMessage.cpp +++ b/test/libwhisper/whisperMessage.cpp @@ -82,7 +82,9 @@ BOOST_AUTO_TEST_SUITE(whisperMessage) BOOST_AUTO_TEST_CASE(seal) { - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing Envelope encryption..."; for (unsigned int i = 1; i < 10; ++i) @@ -91,7 +93,8 @@ BOOST_AUTO_TEST_CASE(seal) BOOST_AUTO_TEST_CASE(work) { - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); cnote << "Testing proof of work..."; Secret zero; diff --git a/test/libwhisper/whisperTopic.cpp b/test/libwhisper/whisperTopic.cpp index 39d953e31..0ea7b2dd5 100644 --- a/test/libwhisper/whisperTopic.cpp +++ b/test/libwhisper/whisperTopic.cpp @@ -47,7 +47,8 @@ BOOST_AUTO_TEST_CASE(topic) return; cnote << "Testing Whisper..."; - VerbosityHolder setTemporaryLevel(0); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(0); uint16_t port1 = 30311; Host host1("Test", NetworkPreferences("127.0.0.1", port1, false)); @@ -161,6 +162,7 @@ BOOST_AUTO_TEST_CASE(forwarding) } }); + // Host must be configured not to share peers. uint16_t port2 = 30313; Host host2("Forwarder", NetworkPreferences("127.0.0.1", port2, false)); @@ -392,7 +394,9 @@ BOOST_AUTO_TEST_CASE(selfAddressed) if (test::Options::get().nonetwork) return; - VerbosityHolder setTemporaryLevel(10); + if (g_logVerbosity != -1) + VerbosityHolder setTemporaryLevel(10); + cnote << "Testing self-addressed messaging with bloom filter matching..."; char const* text = "deterministic pseudorandom test"; From fe6a27c245faede6d6675f09d943f87c4dd86649 Mon Sep 17 00:00:00 2001 From: Dimitry Date: Tue, 11 Aug 2015 14:30:35 +0300 Subject: [PATCH 27/41] error report: merge with latesd develop --- test/TestHelper.cpp | 2 +- test/libethereum/blockchain.cpp | 72 ++++++++++--------- test/libsolidity/solidityExecutionFramework.h | 2 +- 3 files changed, 39 insertions(+), 37 deletions(-) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 80b4214cf..3869613c9 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -320,7 +320,7 @@ int ImportTest::exportTest(bytes const& _output) { int err = 0; // export output - m_TestObject["out"] = (_output.size() > 4096 && !Options::get().fulloutput) ? "#" + toString(_output.size()) : toHex(_output, 2, HexPrefix::Add); + m_testObject["out"] = (_output.size() > 4096 && !Options::get().fulloutput) ? "#" + toString(_output.size()) : toHex(_output, 2, HexPrefix::Add); // compare expected output with post output if (m_testObject.count("expectOut") > 0) diff --git a/test/libethereum/blockchain.cpp b/test/libethereum/blockchain.cpp index 0be4d6622..3ec623685 100644 --- a/test/libethereum/blockchain.cpp +++ b/test/libethereum/blockchain.cpp @@ -53,6 +53,7 @@ mArray importUncles(mObject const& _blObj, vector& _vBiUncles, vect void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) { + string testname; for (auto& i: _v.get_obj()) { mObject& o = i.second.get_obj(); @@ -62,7 +63,8 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) continue; } - cerr << i.first << endl; + cnote << i.first; + testname = "(" + i.first + ") "; TBOOST_REQUIRE(o.count("genesisBlockHeader")); TBOOST_REQUIRE(o.count("pre")); @@ -81,7 +83,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) if (_fillin) biGenesisBlock = constructBlock(o["genesisBlockHeader"].get_obj(), trueState.rootHash()); else - TBOOST_CHECK_MESSAGE((biGenesisBlock.stateRoot() == trueState.rootHash()), "root hash does not match"); + TBOOST_CHECK_MESSAGE((biGenesisBlock.stateRoot() == trueState.rootHash()), testname + "root hash does not match"); if (_fillin) { @@ -381,24 +383,24 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) if (importedAndBest) { //Check the fields restored from RLP to original fields - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.headerHash(WithProof) == blockFromRlp.headerHash(WithProof)), "hash in given RLP not matching the block hash!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.parentHash() == blockFromRlp.parentHash()), "parentHash in given RLP not matching the block parentHash!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.sha3Uncles() == blockFromRlp.sha3Uncles()), "sha3Uncles in given RLP not matching the block sha3Uncles!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.beneficiary() == blockFromRlp.beneficiary()),"beneficiary in given RLP not matching the block beneficiary!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.stateRoot() == blockFromRlp.stateRoot()), "stateRoot in given RLP not matching the block stateRoot!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.transactionsRoot() == blockFromRlp.transactionsRoot()), "transactionsRoot in given RLP not matching the block transactionsRoot!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.receiptsRoot() == blockFromRlp.receiptsRoot()), "receiptsRoot in given RLP not matching the block receiptsRoot!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.logBloom() == blockFromRlp.logBloom()), "logBloom in given RLP not matching the block logBloom!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.difficulty() == blockFromRlp.difficulty()), "difficulty in given RLP not matching the block difficulty!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.number() == blockFromRlp.number()), "number in given RLP not matching the block number!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.gasLimit() == blockFromRlp.gasLimit()),"gasLimit in given RLP not matching the block gasLimit!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.gasUsed() == blockFromRlp.gasUsed()), "gasUsed in given RLP not matching the block gasUsed!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.timestamp() == blockFromRlp.timestamp()), "timestamp in given RLP not matching the block timestamp!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.extraData() == blockFromRlp.extraData()), "extraData in given RLP not matching the block extraData!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.mixHash() == blockFromRlp.mixHash()), "mixHash in given RLP not matching the block mixHash!"); - TBOOST_CHECK_MESSAGE((blockHeaderFromFields.nonce() == blockFromRlp.nonce()), "nonce in given RLP not matching the block nonce!"); - - TBOOST_CHECK_MESSAGE((blockHeaderFromFields == blockFromRlp), "However, blockHeaderFromFields != blockFromRlp!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.headerHash(WithProof) == blockFromRlp.headerHash(WithProof)), testname + "hash in given RLP not matching the block hash!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.parentHash() == blockFromRlp.parentHash()), testname + "parentHash in given RLP not matching the block parentHash!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.sha3Uncles() == blockFromRlp.sha3Uncles()), testname + "sha3Uncles in given RLP not matching the block sha3Uncles!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.beneficiary() == blockFromRlp.beneficiary()), testname + "beneficiary in given RLP not matching the block beneficiary!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.stateRoot() == blockFromRlp.stateRoot()), testname + "stateRoot in given RLP not matching the block stateRoot!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.transactionsRoot() == blockFromRlp.transactionsRoot()), testname + "transactionsRoot in given RLP not matching the block transactionsRoot!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.receiptsRoot() == blockFromRlp.receiptsRoot()), testname + "receiptsRoot in given RLP not matching the block receiptsRoot!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.logBloom() == blockFromRlp.logBloom()), testname + "logBloom in given RLP not matching the block logBloom!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.difficulty() == blockFromRlp.difficulty()), testname + "difficulty in given RLP not matching the block difficulty!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.number() == blockFromRlp.number()), testname + "number in given RLP not matching the block number!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.gasLimit() == blockFromRlp.gasLimit()),"testname + gasLimit in given RLP not matching the block gasLimit!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.gasUsed() == blockFromRlp.gasUsed()), testname + "gasUsed in given RLP not matching the block gasUsed!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.timestamp() == blockFromRlp.timestamp()), testname + "timestamp in given RLP not matching the block timestamp!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.extraData() == blockFromRlp.extraData()), testname + "extraData in given RLP not matching the block extraData!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.mixHash() == blockFromRlp.mixHash()), testname + "mixHash in given RLP not matching the block mixHash!"); + TBOOST_CHECK_MESSAGE((blockHeaderFromFields.nonce() == blockFromRlp.nonce()), testname + "nonce in given RLP not matching the block nonce!"); + + TBOOST_CHECK_MESSAGE((blockHeaderFromFields == blockFromRlp), testname + "However, blockHeaderFromFields != blockFromRlp!"); //Check transaction list @@ -445,18 +447,18 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) for (size_t i = 0; i < txsFromField.size(); ++i) { - TBOOST_CHECK_MESSAGE((txsFromField[i].data() == txsFromRlp[i].data()), "transaction data in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].gas() == txsFromRlp[i].gas()), "transaction gasLimit in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].gasPrice() == txsFromRlp[i].gasPrice()), "transaction gasPrice in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].nonce() == txsFromRlp[i].nonce()), "transaction nonce in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].signature().r == txsFromRlp[i].signature().r), "transaction r in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].signature().s == txsFromRlp[i].signature().s), "transaction s in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].signature().v == txsFromRlp[i].signature().v), "transaction v in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].receiveAddress() == txsFromRlp[i].receiveAddress()), "transaction receiveAddress in rlp and in field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].value() == txsFromRlp[i].value()), "transaction receiveAddress in rlp and in field do not match"); - - TBOOST_CHECK_MESSAGE((txsFromField[i] == txsFromRlp[i]), "transactions from rlp and transaction from field do not match"); - TBOOST_CHECK_MESSAGE((txsFromField[i].rlp() == txsFromRlp[i].rlp()), "transactions rlp do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].data() == txsFromRlp[i].data()), testname + "transaction data in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].gas() == txsFromRlp[i].gas()), testname + "transaction gasLimit in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].gasPrice() == txsFromRlp[i].gasPrice()), testname + "transaction gasPrice in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].nonce() == txsFromRlp[i].nonce()), testname + "transaction nonce in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].signature().r == txsFromRlp[i].signature().r), testname + "transaction r in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].signature().s == txsFromRlp[i].signature().s), testname + "transaction s in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].signature().v == txsFromRlp[i].signature().v), testname + "transaction v in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].receiveAddress() == txsFromRlp[i].receiveAddress()), testname + "transaction receiveAddress in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].value() == txsFromRlp[i].value()), testname + "transaction receiveAddress in rlp and in field do not match"); + + TBOOST_CHECK_MESSAGE((txsFromField[i] == txsFromRlp[i]), testname + "transactions from rlp and transaction from field do not match"); + TBOOST_CHECK_MESSAGE((txsFromField[i].rlp() == txsFromRlp[i].rlp()), testname + "transactions rlp do not match"); } // check uncle list @@ -477,7 +479,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) } catch(...) { - TBOOST_ERROR("invalid uncle header"); + TBOOST_ERROR(testname + "invalid uncle header"); } uBlHsFromField.push_back(uncleBlockHeader); } @@ -494,13 +496,13 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin) TBOOST_REQUIRE_EQUAL(uBlHsFromField.size(), uBlHsFromRlp.size()); for (size_t i = 0; i < uBlHsFromField.size(); ++i) - TBOOST_CHECK_MESSAGE((uBlHsFromField[i] == uBlHsFromRlp[i]), "block header in rlp and in field do not match"); + TBOOST_CHECK_MESSAGE((uBlHsFromField[i] == uBlHsFromRlp[i]), testname + "block header in rlp and in field do not match"); }//importedAndBest }//all blocks TBOOST_REQUIRE((o.count("lastblockhash") > 0)); TBOOST_CHECK_MESSAGE((toString(trueBc.info().hash()) == o["lastblockhash"].get_str()), - "Boost check: " + i.first + " lastblockhash does not match " + toString(trueBc.info().hash()) + " expected: " + o["lastblockhash"].get_str()); + testname + "Boost check: " + i.first + " lastblockhash does not match " + toString(trueBc.info().hash()) + " expected: " + o["lastblockhash"].get_str()); } } } diff --git a/test/libsolidity/solidityExecutionFramework.h b/test/libsolidity/solidityExecutionFramework.h index aac033b50..05f93bb60 100644 --- a/test/libsolidity/solidityExecutionFramework.h +++ b/test/libsolidity/solidityExecutionFramework.h @@ -46,7 +46,7 @@ public: { if (g_logVerbosity != -1) g_logVerbosity = 0; - m_state.resetCurrent(); + //m_state.resetCurrent(); } bytes const& compileAndRunWithoutCheck( From 19ad8b88f037ededf460f52356a715557d05e0f6 Mon Sep 17 00:00:00 2001 From: Dimitry Date: Wed, 12 Aug 2015 11:12:12 +0300 Subject: [PATCH 28/41] nice error report merge --- test/libethereum/transactionTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libethereum/transactionTests.cpp b/test/libethereum/transactionTests.cpp index 4131d7454..d2f7523b0 100644 --- a/test/libethereum/transactionTests.cpp +++ b/test/libethereum/transactionTests.cpp @@ -42,7 +42,7 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) continue; } - testname = "(" + i.first ") "; + testname = "(" + i.first + ") "; cnote << testname; if (_fillin) { From 340dd62448311f75dc388f551bad03f91ef38912 Mon Sep 17 00:00:00 2001 From: Dimitry Date: Wed, 12 Aug 2015 18:53:46 +0300 Subject: [PATCH 29/41] boost issue --- test/boostTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/boostTest.cpp b/test/boostTest.cpp index af546c3a3..79ed27abc 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -23,7 +23,7 @@ #define BOOST_TEST_MODULE EthereumTests #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" -#define BOOST_DISABLE_WIN32 //disables SEH warning +//#define BOOST_DISABLE_WIN32 //disables SEH warning #define BOOST_TEST_NO_MAIN #include #pragma GCC diagnostic pop From 58545a458996418c178ca243bd6e9ed79f71bc61 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 12 Aug 2015 21:19:04 +0200 Subject: [PATCH 30/41] NameRegNamer for NameReg integration. --- alethzero/MainFace.h | 1 + alethzero/MainWin.cpp | 11 ++-- alethzero/MainWin.h | 2 +- alethzero/NameRegNamer.cpp | 106 +++++++++++++++++++++++++++++++++++++ alethzero/NameRegNamer.h | 59 +++++++++++++++++++++ libethcore/ABI.h | 25 ++++++++- 6 files changed, 197 insertions(+), 7 deletions(-) create mode 100644 alethzero/NameRegNamer.cpp create mode 100644 alethzero/NameRegNamer.h diff --git a/alethzero/MainFace.h b/alethzero/MainFace.h index 525cc312d..d6dc3dd42 100644 --- a/alethzero/MainFace.h +++ b/alethzero/MainFace.h @@ -93,6 +93,7 @@ public: virtual unsigned installWatch(dev::eth::LogFilter const& _tf, WatchHandler const& _f) = 0; virtual unsigned installWatch(dev::h256 const& _tf, WatchHandler const& _f) = 0; + virtual void uninstallWatch(unsigned _id) = 0; // Account naming API virtual void install(AccountNamer* _adopt) = 0; diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index a78949413..bcdb42c57 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -94,8 +94,8 @@ QString dev::az::contentsOfQResource(string const& res) } //Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); -Address c_newConfig = Address("c6d9d2cd449a754c494264e1809c50e34d64562b"); -//Address c_nameReg = Address("ddd1cea741d548f90d86fb87a3ae6492e18c03a1"); +//Address c_newConfig = Address("c6d9d2cd449a754c494264e1809c50e34d64562b"); +Address c_nameReg = Address("96d76ae3397b52d9f61215270df65d72358709e3"); Main::Main(QWidget* _parent): MainFace(_parent), @@ -486,8 +486,8 @@ void Main::installWatches() cdebug << "newBlock watch ID: " << newBlockId; cdebug << "newPending watch ID: " << newPendingId; - installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); }); - installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); }); +// installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installNameRegWatch(); }); +// installWatch(LogFilter().address(c_newConfig), [=](LocalisedLogEntries const&) { installCurrenciesWatch(); }); } Address Main::getNameReg() const @@ -498,7 +498,8 @@ Address Main::getNameReg() const Address Main::getCurrencies() const { - return abiOut
(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)3)).output); +// return abiOut
(ethereum()->call(c_newConfig, abiIn("lookup(uint256)", (u256)3)).output); + return Address(); } bool Main::doConfirm() diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index b23a33697..e02fb5f4a 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -240,7 +240,7 @@ private: unsigned installWatch(eth::LogFilter const& _tf, WatchHandler const& _f) override; unsigned installWatch(h256 const& _tf, WatchHandler const& _f) override; - void uninstallWatch(unsigned _w); + void uninstallWatch(unsigned _w) override; void keysChanged(); diff --git a/alethzero/NameRegNamer.cpp b/alethzero/NameRegNamer.cpp new file mode 100644 index 000000000..fd2f054b3 --- /dev/null +++ b/alethzero/NameRegNamer.cpp @@ -0,0 +1,106 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file NameRegNamer.h + * @author Gav Wood + * @date 2015 + */ + +#include "NameRegNamer.h" +#include +#include +using namespace std; +using namespace dev; +using namespace az; +using namespace eth; + +DEV_AZ_NOTE_PLUGIN(NameRegNamer); + +NameRegNamer::NameRegNamer(MainFace* _m): + AccountNamerPlugin(_m, "NameRegNamer") +{ +} + +NameRegNamer::~NameRegNamer() +{ +} + +string NameRegNamer::toName(Address const& _a) const +{ + for (auto const& r: m_registrars) + { + string n = abiOut(main()->ethereum()->call(r, abiIn("name(address)", _a)).output); + if (!n.empty()) + return n; + } + return string(); +} + +Address NameRegNamer::toAddress(std::string const& _n) const +{ + for (auto const& r: m_registrars) + if (Address a = abiOut
(main()->ethereum()->call(r, abiIn("addr(string)", _n)).output)) + return a; + return Address(); +} + +Addresses NameRegNamer::knownAddresses() const +{ + return m_knownCache; +} + +void NameRegNamer::killRegistrar(Address const& _r) +{ + if (m_filters.count(_r)) + { + main()->uninstallWatch(m_filters.at(_r)); + m_filters.erase(_r); + } + for (auto i = m_registrars.begin(); i != m_registrars.end();) + if (*i == _r) + i = m_registrars.erase(i); + else + ++i; +} + +void NameRegNamer::updateCache() +{ +// m_forwardCache.clear(); +// m_reverseCache.clear(); + m_knownCache.clear(); +#if ETH_FATDB || !ETH_TRUE + for (auto const& r: m_registrars) + for (u256 const& a: keysOf(ethereum()->storageAt(r))) + if (a < u256(1) << 160) + m_knownCache.push_back(Address((u160)a - 1)); +#endif +} + +void NameRegNamer::readSettings(QSettings const& _s) +{ + (void)_s; + while (!m_registrars.empty()) + killRegistrar(m_registrars.back()); + + Address a("96d76ae3397b52d9f61215270df65d72358709e3"); + m_filters[a] = main()->installWatch(LogFilter().address(a), [=](LocalisedLogEntries const&){ updateCache(); }); + + noteKnownChanged(); +} + +void NameRegNamer::writeSettings(QSettings&) +{ +} diff --git a/alethzero/NameRegNamer.h b/alethzero/NameRegNamer.h new file mode 100644 index 000000000..d56e9d41b --- /dev/null +++ b/alethzero/NameRegNamer.h @@ -0,0 +1,59 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file NameRegNamer.h + * @author Gav Wood + * @date 2015 + */ + +#pragma once + +#include "MainFace.h" + +namespace dev +{ +namespace az +{ + +class NameRegNamer: public QObject, public AccountNamerPlugin +{ + Q_OBJECT + +public: + NameRegNamer(MainFace* _m); + ~NameRegNamer(); + +private: + void readSettings(QSettings const&) override; + void writeSettings(QSettings&) override; + + std::string toName(Address const&) const override; + Address toAddress(std::string const&) const override; + Addresses knownAddresses() const override; + + void updateCache(); + void killRegistrar(Address const& _r); + + Addresses m_registrars; + std::unordered_map m_filters; + + mutable Addresses m_knownCache; +// mutable std::unordered_map m_forwardCache; +// mutable std::unordered_map m_reverseCache; +}; + +} +} diff --git a/libethcore/ABI.h b/libethcore/ABI.h index 7d7be90dd..5b7d160d0 100644 --- a/libethcore/ABI.h +++ b/libethcore/ABI.h @@ -43,7 +43,17 @@ template struct ABISerialiser {}; template struct ABISerialiser> { static bytes serialise(FixedHash const& _t) { static_assert(N <= 32, "Cannot serialise hash > 32 bytes."); static_assert(N > 0, "Cannot serialise zero-length hash."); return bytes(32 - N, 0) + _t.asBytes(); } }; template <> struct ABISerialiser { static bytes serialise(u256 const& _t) { return h256(_t).asBytes(); } }; template <> struct ABISerialiser { static bytes serialise(u160 const& _t) { return bytes(12, 0) + h160(_t).asBytes(); } }; -template <> struct ABISerialiser { static bytes serialise(string32 const& _t) { return bytesConstRef((byte const*)_t.data(), 32).toBytes(); } }; +template <> struct ABISerialiser { static bytes serialise(string32 const& _t) { bytes ret; bytesConstRef((byte const*)_t.data(), 32).populate(bytesRef(&ret)); return ret; } }; +template <> struct ABISerialiser +{ + static bytes serialise(std::string const& _t) + { + bytes ret = h256(u256(32)).asBytes() + h256(u256(_t.size())).asBytes(); + ret.resize(ret.size() + (_t.size() + 31) / 32 * 32); + bytesConstRef(&_t).populate(bytesRef(&ret).cropped(64)); + return ret; + } +}; inline bytes abiInAux() { return {}; } template bytes abiInAux(T const& _t, U const& ... _u) @@ -61,6 +71,19 @@ template struct ABIDeserialiser> { static FixedHash template <> struct ABIDeserialiser { static u256 deserialise(bytesConstRef& io_t) { u256 ret = fromBigEndian(io_t.cropped(0, 32)); io_t = io_t.cropped(32); return ret; } }; template <> struct ABIDeserialiser { static u160 deserialise(bytesConstRef& io_t) { u160 ret = fromBigEndian(io_t.cropped(12, 20)); io_t = io_t.cropped(32); return ret; } }; template <> struct ABIDeserialiser { static string32 deserialise(bytesConstRef& io_t) { string32 ret; io_t.cropped(0, 32).populate(bytesRef((byte*)ret.data(), 32)); io_t = io_t.cropped(32); return ret; } }; +template <> struct ABIDeserialiser +{ + static std::string deserialise(bytesConstRef& io_t) + { + unsigned o = (uint16_t)u256(h256(io_t.cropped(0, 32))); + unsigned s = (uint16_t)u256(h256(io_t.cropped(o, 32))); + std::string ret; + ret.resize(s); + io_t.cropped(o + 32, s).populate(bytesRef((byte*)ret.data(), s)); + io_t = io_t.cropped(32); + return ret; + } +}; template T abiOut(bytes const& _data) { From e69c0e06542afb8ed8ccd5c60d383595447b47c3 Mon Sep 17 00:00:00 2001 From: Dimitry Date: Thu, 13 Aug 2015 12:18:29 +0300 Subject: [PATCH 31/41] Error report: style issues --- test/TestHelper.cpp | 5 ++--- test/boostTest.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 3869613c9..15a5d5633 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -319,7 +319,7 @@ int ImportTest::compareStates(State const& _stateExpect, State const& _statePost int ImportTest::exportTest(bytes const& _output) { int err = 0; - // export output + // export output m_testObject["out"] = (_output.size() > 4096 && !Options::get().fulloutput) ? "#" + toString(_output.size()) : toHex(_output, 2, HexPrefix::Add); // compare expected output with post output @@ -797,8 +797,7 @@ Options::Options() std::cout.rdbuf(strCout.rdbuf()); std::cerr.rdbuf(strCout.rdbuf()); } - else - if (indentLevel == "1") + else if (indentLevel == "1") logVerbosity = Verbosity::NiceReport; else logVerbosity = Verbosity::Full; diff --git a/test/boostTest.cpp b/test/boostTest.cpp index 79ed27abc..824a8e8e5 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -62,20 +62,20 @@ int main( int argc, char* argv[] ) ? boost::exit_success : results_collector.results( framework::master_test_suite().p_id ).result_code(); } - catch( framework::nothing_to_test const& ) { + catch (framework::nothing_to_test const&) { return boost::exit_success; } - catch( framework::internal_error const& ex ) { + catch (framework::internal_error const& ex) { results_reporter::get_stream() << "Boost.Test framework internal error: " << ex.what() << std::endl; return boost::exit_exception_failure; } - catch( framework::setup_error const& ex ) { + catch (framework::setup_error const& ex) { results_reporter::get_stream() << "Test setup error: " << ex.what() << std::endl; return boost::exit_exception_failure; } - catch( ... ) { + catch (...) { results_reporter::get_stream() << "Boost.Test framework internal error: unknown reason" << std::endl; return boost::exit_exception_failure; From 2632a40d42f5a8b5dafef2f1bc0babcf9128baeb Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 13 Aug 2015 11:31:21 +0200 Subject: [PATCH 32/41] fixed block mining --- mix/MixClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 2d43ddc96..7d2125436 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -269,7 +269,7 @@ void MixClient::mine() RLPStream header; h.streamRLP(header); m_postMine.sealBlock(header.out()); - bc().import(m_postMine.blockData(), m_stateDB, (ImportRequirements::Everything & ~ImportRequirements::ValidSeal) != 0); + bc().import(m_postMine.blockData(), m_postMine.state().db(), (ImportRequirements::Everything & ~ImportRequirements::ValidSeal) != 0); m_postMine.sync(bc()); m_preMine = m_postMine; } From b7c28a09aaf472f1badd84b2aee59fbbaea69ba5 Mon Sep 17 00:00:00 2001 From: Vlad Gluhovsky Date: Thu, 13 Aug 2015 00:07:05 +0200 Subject: [PATCH 33/41] required peers are not added to the node table --- libp2p/Host.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 9086664a4..2356e10be 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -530,14 +530,8 @@ void Host::connect(std::shared_ptr const& _p) return; } - if (!!m_nodeTable && !m_nodeTable->haveNode(_p->id)) - { - // connect was attempted, so try again by adding to node table - m_nodeTable->addNode(*_p.get()); - // abort unless peer is required - if (!_p->required) - return; - } + if (!!m_nodeTable && !m_nodeTable->haveNode(_p->id) && !_p->required) + return; // prevent concurrently connecting to a node Peer *nptr = _p.get(); From 1b1ba5f8f8bde9b12bda0595870d8c64c6543e1e Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 13 Aug 2015 12:07:45 +0200 Subject: [PATCH 34/41] allow adding transactions for not yet deplyed contract --- mix/ClientModel.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index f5e978971..d5973ce5e 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -446,9 +446,13 @@ void ClientModel::executeSequence(vector const& _sequence) if (contractAddressIter == m_contractAddresses.end()) { emit runFailed("Contract '" + transaction.contractId + tr(" not deployed.") + "' " + tr(" Cannot call ") + transaction.functionId); - break; + Address fakeAddress = Address::random(); + std::pair contractToken = resolvePair(transaction.contractId); + m_contractNames[fakeAddress] = contractToken.first; + callAddress(fakeAddress, encoder.encodedData(), transaction); //Transact to a random fake address to that transaction is added to the list anyway } - callAddress(contractAddressIter->second, encoder.encodedData(), transaction); + else + callAddress(contractAddressIter->second, encoder.encodedData(), transaction); } m_gasCosts.append(m_client->lastExecution().gasUsed); onNewTransaction(); @@ -833,9 +837,9 @@ void ClientModel::onNewTransaction() else { //transaction/call - if (tr.transactionData.size() > 0 && tr.transactionData.front().size() >= 4) + if (tr.inputParameters.size() >= 4) { - functionHash = FixedHash<4>(tr.transactionData.front().data(), FixedHash<4>::ConstructFromPointer); + functionHash = FixedHash<4>(tr.inputParameters.data(), FixedHash<4>::ConstructFromPointer); function = QString::fromStdString(toJS(functionHash)); abi = true; } From e92298e8ee76f0d2a1958baba3a5a81c22edcc23 Mon Sep 17 00:00:00 2001 From: Dimitry Date: Thu, 13 Aug 2015 13:27:47 +0300 Subject: [PATCH 35/41] error report: style --- test/boostTest.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/test/boostTest.cpp b/test/boostTest.cpp index 824a8e8e5..f448c48e3 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -18,6 +18,7 @@ * @author Marko Simovic * @date 2014 * Stub for generating main boost.test module. + * Original code taken from boost sources. */ #define BOOST_TEST_MODULE EthereumTests @@ -45,10 +46,12 @@ test_suite* init_func( int argc, char* argv[] ) //Custom Boost Unit Test Main int main( int argc, char* argv[] ) { - try { + try + { framework::init( init_func, argc, argv ); - if( !runtime_config::test_to_run().is_empty() ) { + if( !runtime_config::test_to_run().is_empty() ) + { test_case_filter filter( runtime_config::test_to_run() ); traverse_test_tree( framework::master_test_suite().p_id, filter ); @@ -62,20 +65,24 @@ int main( int argc, char* argv[] ) ? boost::exit_success : results_collector.results( framework::master_test_suite().p_id ).result_code(); } - catch (framework::nothing_to_test const&) { + catch (framework::nothing_to_test const&) + { return boost::exit_success; } - catch (framework::internal_error const& ex) { + catch (framework::internal_error const& ex) + { results_reporter::get_stream() << "Boost.Test framework internal error: " << ex.what() << std::endl; return boost::exit_exception_failure; } - catch (framework::setup_error const& ex) { + catch (framework::setup_error const& ex) + { results_reporter::get_stream() << "Test setup error: " << ex.what() << std::endl; return boost::exit_exception_failure; } - catch (...) { + catch (...) + { results_reporter::get_stream() << "Boost.Test framework internal error: unknown reason" << std::endl; return boost::exit_exception_failure; From 9122153f2739e04623bf3213652441486f3c72f1 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 13 Aug 2015 13:13:59 +0200 Subject: [PATCH 36/41] NameReg integration. Minor other alterations. --- alethzero/MainWin.cpp | 4 ++-- alethzero/NameRegNamer.cpp | 5 +++-- eth/main.cpp | 8 ++++---- libethereum/ClientBase.h | 2 +- libethereum/GasPricer.h | 6 +++--- libethereum/Interface.h | 8 ++++---- libethereumx/Ethereum.h | 6 +++--- test/libethereum/gaspricer.cpp | 8 ++++---- 8 files changed, 24 insertions(+), 23 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index bcdb42c57..c2e3d5c84 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -924,8 +924,8 @@ void Main::readSettings(bool _skipGeometry) { p->readSettings(s); }); - static_cast(ethereum()->gasPricer().get())->setAsk(u256(s.value("askPrice", QString::fromStdString(toString(c_defaultGasPrice))).toString().toStdString())); - static_cast(ethereum()->gasPricer().get())->setBid(u256(s.value("bidPrice", QString::fromStdString(toString(c_defaultGasPrice))).toString().toStdString())); + static_cast(ethereum()->gasPricer().get())->setAsk(u256(s.value("askPrice", QString::fromStdString(toString(DefaultGasPrice))).toString().toStdString())); + static_cast(ethereum()->gasPricer().get())->setBid(u256(s.value("bidPrice", QString::fromStdString(toString(DefaultGasPrice))).toString().toStdString())); ui->upnp->setChecked(s.value("upnp", true).toBool()); ui->forcePublicIP->setText(s.value("forceAddress", "").toString()); diff --git a/alethzero/NameRegNamer.cpp b/alethzero/NameRegNamer.cpp index fd2f054b3..c0ed9b3a5 100644 --- a/alethzero/NameRegNamer.cpp +++ b/alethzero/NameRegNamer.cpp @@ -42,7 +42,7 @@ string NameRegNamer::toName(Address const& _a) const { for (auto const& r: m_registrars) { - string n = abiOut(main()->ethereum()->call(r, abiIn("name(address)", _a)).output); + string n = abiOut(main()->ethereum()->call(Address(1), 0, r, abiIn("name(address)", _a), 1000000, DefaultGasPrice, PendingBlock, FudgeFactor::Lenient).output); if (!n.empty()) return n; } @@ -95,7 +95,8 @@ void NameRegNamer::readSettings(QSettings const& _s) while (!m_registrars.empty()) killRegistrar(m_registrars.back()); - Address a("96d76ae3397b52d9f61215270df65d72358709e3"); + Address a("047cdba9627a8686bb24b3a65d87dab7efa53d31"); + m_registrars.push_back(a); m_filters[a] = main()->installWatch(LogFilter().address(a), [=](LocalisedLogEntries const&){ updateCache(); }); noteKnownChanged(); diff --git a/eth/main.cpp b/eth/main.cpp index 13ef5fc00..b33ee0028 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -109,8 +109,8 @@ void help() /*<< " -B,--block-fees Set the block fee profit in the reference unit e.g. ¢ (default: 15)." << endl << " -e,--ether-price Set the ether price in the reference unit e.g. ¢ (default: 30.679)." << endl << " -P,--priority <0 - 100> Default % priority of a transaction (default: 50)." << endl*/ - << " --ask Set the minimum ask gas price under which no transactions will be mined (default " << toString(c_defaultGasPrice) << " )." << endl - << " --bid Set the bid gas price for to pay for transactions (default " << toString(c_defaultGasPrice) << " )." << endl + << " --ask Set the minimum ask gas price under which no transactions will be mined (default " << toString(DefaultGasPrice) << " )." << endl + << " --bid Set the bid gas price for to pay for transactions (default " << toString(DefaultGasPrice) << " )." << endl << endl << "Client mining:" << endl << " -a,--address Set the coinbase (mining payout) address to addr (default: auto)." << endl @@ -337,8 +337,8 @@ int main(int argc, char** argv) // TransactionPriority priority = TransactionPriority::Medium; // double etherPrice = 30.679; // double blockFees = 15.0; - u256 askPrice = c_defaultGasPrice; - u256 bidPrice = c_defaultGasPrice; + u256 askPrice = DefaultGasPrice; + u256 bidPrice = DefaultGasPrice; // javascript console bool useConsole = false; diff --git a/libethereum/ClientBase.h b/libethereum/ClientBase.h index e5e93e5d1..504fb2dbd 100644 --- a/libethereum/ClientBase.h +++ b/libethereum/ClientBase.h @@ -148,7 +148,7 @@ public: using Interface::addresses; virtual Addresses addresses(BlockNumber _block) const override; virtual u256 gasLimitRemaining() const override; - virtual u256 gasBidPrice() const override { return c_defaultGasPrice; } + virtual u256 gasBidPrice() const override { return DefaultGasPrice; } /// Get the coinbase address virtual Address address() const override; diff --git a/libethereum/GasPricer.h b/libethereum/GasPricer.h index 9a89fe94d..47867fee7 100644 --- a/libethereum/GasPricer.h +++ b/libethereum/GasPricer.h @@ -40,7 +40,7 @@ enum class TransactionPriority Highest = 8 }; -static const u256 c_defaultGasPrice = 50 * shannon; +static const u256 DefaultGasPrice = 50 * shannon; class GasPricer { @@ -68,8 +68,8 @@ public: u256 bid(TransactionPriority = TransactionPriority::Medium) const override { return m_bid; } private: - u256 m_ask = c_defaultGasPrice; - u256 m_bid = c_defaultGasPrice; + u256 m_ask = DefaultGasPrice; + u256 m_bid = DefaultGasPrice; }; } diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 9c109000f..ed9659f3b 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -71,25 +71,25 @@ public: virtual std::pair submitTransaction(TransactionSkeleton const& _t, Secret const& _secret) = 0; /// Submits the given message-call transaction. - void submitTransaction(Secret const& _secret, u256 const& _value, Address const& _dest, bytes const& _data = bytes(), u256 const& _gas = 10000, u256 const& _gasPrice = c_defaultGasPrice, u256 const& _nonce = UndefinedU256); + void submitTransaction(Secret const& _secret, u256 const& _value, Address const& _dest, bytes const& _data = bytes(), u256 const& _gas = 1000000, u256 const& _gasPrice = DefaultGasPrice, u256 const& _nonce = UndefinedU256); /// Submits a new contract-creation transaction. /// @returns the new contract's address (assuming it all goes through). - Address submitTransaction(Secret const& _secret, u256 const& _endowment, bytes const& _init, u256 const& _gas = 10000, u256 const& _gasPrice = c_defaultGasPrice, u256 const& _nonce = UndefinedU256); + Address submitTransaction(Secret const& _secret, u256 const& _endowment, bytes const& _init, u256 const& _gas = 1000000, u256 const& _gasPrice = DefaultGasPrice, u256 const& _nonce = UndefinedU256); /// Blocks until all pending transactions have been processed. virtual void flushTransactions() = 0; /// Makes the given call. Nothing is recorded into the state. virtual ExecutionResult call(Address const& _from, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0; - ExecutionResult call(Address const& _from, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = c_defaultGasPrice, FudgeFactor _ff = FudgeFactor::Strict) { return call(_from, _value, _dest, _data, _gas, _gasPrice, m_default, _ff); } + ExecutionResult call(Address const& _from, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 1000000, u256 _gasPrice = DefaultGasPrice, FudgeFactor _ff = FudgeFactor::Strict) { return call(_from, _value, _dest, _data, _gas, _gasPrice, m_default, _ff); } ExecutionResult call(Secret const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) { return call(toAddress(_secret), _value, _dest, _data, _gas, _gasPrice, _blockNumber, _ff); } ExecutionResult call(Secret const& _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, FudgeFactor _ff = FudgeFactor::Strict) { return call(toAddress(_secret), _value, _dest, _data, _gas, _gasPrice, _ff); } /// Does the given creation. Nothing is recorded into the state. /// @returns the pair of the Address of the created contract together with its code. virtual ExecutionResult create(Address const& _from, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) = 0; - ExecutionResult create(Address const& _from, u256 _value, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = c_defaultGasPrice, FudgeFactor _ff = FudgeFactor::Strict) { return create(_from, _value, _data, _gas, _gasPrice, m_default, _ff); } + ExecutionResult create(Address const& _from, u256 _value, bytes const& _data = bytes(), u256 _gas = 1000000, u256 _gasPrice = DefaultGasPrice, FudgeFactor _ff = FudgeFactor::Strict) { return create(_from, _value, _data, _gas, _gasPrice, m_default, _ff); } ExecutionResult create(Secret const& _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, FudgeFactor _ff = FudgeFactor::Strict) { return create(toAddress(_secret), _value, _data, _gas, _gasPrice, _blockNumber, _ff); } ExecutionResult create(Secret const& _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, FudgeFactor _ff = FudgeFactor::Strict) { return create(toAddress(_secret), _value, _data, _gas, _gasPrice, _ff); } diff --git a/libethereumx/Ethereum.h b/libethereumx/Ethereum.h index 73392ea88..50eab0de3 100644 --- a/libethereumx/Ethereum.h +++ b/libethereumx/Ethereum.h @@ -62,11 +62,11 @@ public: ~Ethereum(); /// Submits the given message-call transaction. - void submitTransaction(Secret const& _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = c_defaultGasPrice); + void submitTransaction(Secret const& _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = DefaultGasPrice); /// Submits a new contract-creation transaction. /// @returns the new contract's address (assuming it all goes through). - Address submitTransaction(Secret const& _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = c_defaultGasPrice); + Address submitTransaction(Secret const& _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = DefaultGasPrice); /// Injects the RLP-encoded transaction given by the _rlp into the transaction queue directly. void inject(bytesConstRef _rlp); @@ -75,7 +75,7 @@ public: void flushTransactions(); /// Makes the given call. Nothing is recorded into the state. - bytes call(Address const& _from, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = c_defaultGasPrice); + bytes call(Address const& _from, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = DefaultGasPrice); // Informational stuff diff --git a/test/libethereum/gaspricer.cpp b/test/libethereum/gaspricer.cpp index f5a6b50be..8f54b05ea 100644 --- a/test/libethereum/gaspricer.cpp +++ b/test/libethereum/gaspricer.cpp @@ -55,13 +55,13 @@ BOOST_AUTO_TEST_CASE(trivialGasPricer) { cnote << "trivialGasPricer"; std::shared_ptr gp(new TrivialGasPricer); - BOOST_CHECK_EQUAL(gp->ask(Block()), c_defaultGasPrice); - BOOST_CHECK_EQUAL(gp->bid(), c_defaultGasPrice); + BOOST_CHECK_EQUAL(gp->ask(Block()), DefaultGasPrice); + BOOST_CHECK_EQUAL(gp->bid(), DefaultGasPrice); bytes bl = CanonBlockChain::createGenesisBlock(); gp->update(FullBlockChain(bl, AccountMap(), TransientDirectory().path(), WithExisting::Kill)); - BOOST_CHECK_EQUAL(gp->ask(Block()), c_defaultGasPrice); - BOOST_CHECK_EQUAL(gp->bid(), c_defaultGasPrice); + BOOST_CHECK_EQUAL(gp->ask(Block()), DefaultGasPrice); + BOOST_CHECK_EQUAL(gp->bid(), DefaultGasPrice); } BOOST_AUTO_TEST_CASE(basicGasPricerNoUpdate) From b8dc1fed0c9a2c7277503e9be231aa9373ba9184 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 13 Aug 2015 15:00:25 +0200 Subject: [PATCH 37/41] Windows build fix. --- alethzero/NameRegNamer.cpp | 1 + alethzero/Transact.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/alethzero/NameRegNamer.cpp b/alethzero/NameRegNamer.cpp index c0ed9b3a5..312fcbc18 100644 --- a/alethzero/NameRegNamer.cpp +++ b/alethzero/NameRegNamer.cpp @@ -20,6 +20,7 @@ */ #include "NameRegNamer.h" +#include #include #include using namespace std; diff --git a/alethzero/Transact.h b/alethzero/Transact.h index 60d4a3c2e..015e9d3cc 100644 --- a/alethzero/Transact.h +++ b/alethzero/Transact.h @@ -105,6 +105,8 @@ private: MainFace* m_main = nullptr; NatSpecFace* m_natSpecDB = nullptr; bool m_allGood = false; + + bool m_determiningGas = false; }; } From 4f0b7bfbaa95fb2fba88e74ccb5233a79f8b4a13 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 13 Aug 2015 15:51:32 +0200 Subject: [PATCH 38/41] whisper panels moved to plugins --- alethzero/CMakeLists.txt | 12 +- alethzero/Main.ui | 231 +-------------------- alethzero/MainFace.cpp | 1 + alethzero/MainFace.h | 2 + alethzero/MainWin.cpp | 160 -------------- alethzero/MainWin.h | 11 +- alethzero/OurWebThreeStubServer.cpp | 2 +- alethzero/plugins/whisper/Whisper.cpp | 177 ++++++++++++++++ alethzero/plugins/whisper/Whisper.h | 60 ++++++ alethzero/plugins/whisper/Whisper.ui | 176 ++++++++++++++++ alethzero/plugins/whisper/WhisperPeers.cpp | 78 +++++++ alethzero/plugins/whisper/WhisperPeers.h | 55 +++++ alethzero/plugins/whisper/WhisperPeers.ui | 32 +++ 13 files changed, 596 insertions(+), 401 deletions(-) create mode 100644 alethzero/plugins/whisper/Whisper.cpp create mode 100644 alethzero/plugins/whisper/Whisper.h create mode 100644 alethzero/plugins/whisper/Whisper.ui create mode 100644 alethzero/plugins/whisper/WhisperPeers.cpp create mode 100644 alethzero/plugins/whisper/WhisperPeers.h create mode 100644 alethzero/plugins/whisper/WhisperPeers.ui diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 29bfed259..045b6042d 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -14,6 +14,16 @@ endif () set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) +file(GLOB_RECURSE SRC_LIST "./plugins/*.cpp") +file(GLOB_RECURSE HEADERS "./plugins/*.h") +file(GLOB_RECURSE PLUGIN_UI "./plugins/*.ui") +aux_source_directory(. SRC_LIST) + +file(GLOB_RECURSE PLUGIN_UI RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/plugins/*.ui") +foreach(ITEM ${PLUGIN_UI}) + get_filename_component(UI_NAME ${ITEM} NAME_WE) + qt5_wrap_ui(ui_${UI_NAME}.h ./${ITEM}) +endforeach() include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) include_directories(BEFORE ..) @@ -54,7 +64,7 @@ endif () # eth_add_executable is defined in cmake/EthExecutableHelper.cmake eth_add_executable(${EXECUTABLE} ICON alethzero - UI_RESOURCES alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui ExportState.ui GetPassword.ui GasPricing.ui AllAccounts.ui LogPanel.ui BrainWallet.ui OtherAccounts.ui + UI_RESOURCES ${PLUGIN_UI} alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui ExportState.ui GetPassword.ui GasPricing.ui AllAccounts.ui LogPanel.ui BrainWallet.ui OtherAccounts.ui WIN_RESOURCES alethzero.rc ) diff --git a/alethzero/Main.ui b/alethzero/Main.ui index b059b4e07..95f25b694 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -210,11 +210,10 @@ - + &Whisper - @@ -236,7 +235,7 @@ - + @@ -979,224 +978,6 @@ font-size: 14pt - - - QDockWidget::DockWidgetFeatureMask - - - Whisper - - - 1 - - - - - - - - 0 - 0 - - - - Data - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Work to Prove - - - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - 0 - - - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - 0 - - - - - - - false - - - - - - - - 0 - 0 - - - - Topic - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - To - - - - - - - true - - - - - - - seconds - - - 5 - - - 259200 - - - - - - - - 0 - 0 - - - - TTL - - - - - - - - 0 - 0 - - - - From - - - - - - - ms - - - 1 - - - 1000 - - - 50 - - - - - - - Post - - - - - - - - - QDockWidget::DockWidgetFeatureMask - - - Active Whispers - - - 2 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - - - - &Quit @@ -1636,13 +1417,6 @@ font-size: 14pt - shhTo - shhFrom - shhTtl - shhTopic - shhWork - shhData - post tabWidget urlEdit listenIP @@ -1652,7 +1426,6 @@ font-size: 14pt blockChainFilter nameReg nodes - whispers jsInput diff --git a/alethzero/MainFace.cpp b/alethzero/MainFace.cpp index 5c9651f73..9382fdf26 100644 --- a/alethzero/MainFace.cpp +++ b/alethzero/MainFace.cpp @@ -58,6 +58,7 @@ QDockWidget* Plugin::dock(Qt::DockWidgetArea _area, QString _title) if (!m_dock) { m_dock = new QDockWidget(_title, m_main); + m_dock->setObjectName(_title); m_main->addDockWidget(_area, m_dock); m_dock->setFeatures(QDockWidget::AllDockWidgetFeatures | QDockWidget::DockWidgetVerticalTitleBar); } diff --git a/alethzero/MainFace.h b/alethzero/MainFace.h index d6dc3dd42..2c25b0584 100644 --- a/alethzero/MainFace.h +++ b/alethzero/MainFace.h @@ -49,6 +49,7 @@ namespace az class Plugin; class MainFace; class Main; +class OurWebThreeStubServer; using WatchHandler = std::function; @@ -89,6 +90,7 @@ public: // TODO: provide a set of available web3 modules. virtual dev::WebThreeDirect* web3() const = 0; virtual dev::eth::Client* ethereum() const = 0; + virtual OurWebThreeStubServer* web3Server() const = 0; virtual std::shared_ptr whisper() const = 0; virtual unsigned installWatch(dev::eth::LogFilter const& _tf, WatchHandler const& _f) = 0; diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index c2e3d5c84..7327f63a5 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -197,8 +197,6 @@ Main::Main(QWidget* _parent): auto w3ss = new OurWebThreeStubServer(*m_httpConnector, this); m_server.reset(w3ss); auto sessionKey = w3ss->newSession(SessionPermissions{{Privilege::Admin}}); - connect(&*m_server, SIGNAL(onNewId(QString)), SLOT(addNewId(QString))); - m_server->setIdentities(keysAsVector(owned())); m_server->StartListening(); WebPage* webPage = new WebPage(this); @@ -387,29 +385,6 @@ void Main::on_sentinel_triggered() ethereum()->setSentinel(sentinel.toStdString()); } -void Main::on_newIdentity_triggered() -{ - KeyPair kp = KeyPair::create(); - m_myIdentities.append(kp); - m_server->setIdentities(keysAsVector(owned())); - refreshWhisper(); -} - -void Main::refreshWhisper() -{ - ui->shhFrom->clear(); - for (auto i: m_server->ids()) - ui->shhFrom->addItem(QString::fromStdString(toHex(i.first.ref()))); -} - -void Main::addNewId(QString _ids) -{ - KeyPair kp(jsToSecret(_ids.toStdString())); - m_myIdentities.push_back(kp); - m_server->setIdentities(keysAsVector(owned())); - refreshWhisper(); -} - NetworkPreferences Main::netPrefs() const { auto listenIP = ui->listenIP->text().toStdString(); @@ -666,17 +641,6 @@ void Main::addConsoleMessage(QString const& _js, QString const& _s) ui->jsConsole->setHtml(r); } -static Public stringToPublic(QString const& _a) -{ - string sn = _a.toStdString(); - if (_a.size() == sizeof(Public) * 2) - return Public(fromHex(_a.toStdString())); - else if (_a.size() == sizeof(Public) * 2 + 2 && _a.startsWith("0x")) - return Public(fromHex(_a.mid(2).toStdString())); - else - return Public(); -} - std::string Main::pretty(dev::Address const& _a) const { auto g_newNameReg = getNameReg(); @@ -807,17 +771,6 @@ void Main::writeSettings() { QSettings s("ethereum", "alethzero"); s.remove("address"); - { - QByteArray b; - b.resize(sizeof(Secret) * m_myIdentities.size()); - auto p = b.data(); - for (auto i: m_myIdentities) - { - memcpy(p, &(i.secret()), sizeof(Secret)); - p += sizeof(Secret); - } - s.setValue("identities", b); - } forEach([&](std::shared_ptr p) { @@ -905,21 +858,6 @@ void Main::readSettings(bool _skipGeometry) restoreGeometry(s.value("geometry").toByteArray()); restoreState(s.value("windowState").toByteArray()); - { - m_myIdentities.clear(); - QByteArray b = s.value("identities").toByteArray(); - if (!b.isEmpty()) - { - Secret k; - for (unsigned i = 0; i < b.size() / sizeof(Secret); ++i) - { - memcpy(k.writable().data(), b.data() + i * sizeof(Secret), sizeof(Secret)); - if (!count(m_myIdentities.begin(), m_myIdentities.end(), KeyPair(k))) - m_myIdentities.append(KeyPair(k)); - } - } - } - forEach([&](std::shared_ptr p) { p->readSettings(s); @@ -1523,7 +1461,6 @@ void Main::timerEvent(QTimerEvent*) { interval = 0; refreshNetwork(); - refreshWhispers(); refreshCache(); refreshBlockCount(); poll(); @@ -1953,60 +1890,6 @@ void Main::on_ourAccounts_doubleClicked() m_logHistory.clear(); }*/ -static shh::Topics topicFromText(QString _s) -{ - shh::BuildTopic ret; - while (_s.size()) - { - QRegExp r("(@|\\$)?\"([^\"]*)\"(\\s.*)?"); - QRegExp d("(@|\\$)?([0-9]+)(\\s*(ether)|(finney)|(szabo))?(\\s.*)?"); - QRegExp h("(@|\\$)?(0x)?(([a-fA-F0-9])+)(\\s.*)?"); - bytes part; - if (r.exactMatch(_s)) - { - for (auto i: r.cap(2)) - part.push_back((byte)i.toLatin1()); - if (r.cap(1) != "$") - for (int i = r.cap(2).size(); i < 32; ++i) - part.push_back(0); - else - part.push_back(0); - _s = r.cap(3); - } - else if (d.exactMatch(_s)) - { - u256 v(d.cap(2).toStdString()); - if (d.cap(6) == "szabo") - v *= szabo; - else if (d.cap(5) == "finney") - v *= finney; - else if (d.cap(4) == "ether") - v *= ether; - bytes bs = dev::toCompactBigEndian(v); - if (d.cap(1) != "$") - for (auto i = bs.size(); i < 32; ++i) - part.push_back(0); - for (auto b: bs) - part.push_back(b); - _s = d.cap(7); - } - else if (h.exactMatch(_s)) - { - bytes bs = fromHex((((h.cap(3).size() & 1) ? "0" : "") + h.cap(3)).toStdString()); - if (h.cap(1) != "$") - for (auto i = bs.size(); i < 32; ++i) - part.push_back(0); - for (auto b: bs) - part.push_back(b); - _s = h.cap(5); - } - else - _s = _s.mid(1); - ret.shift(part); - } - return ret; -} - void Main::on_clearPending_triggered() { writeSettings(); @@ -2293,19 +2176,6 @@ std::string Main::prettyU256(dev::u256 const& _n) const return s.str(); } -void Main::on_post_clicked() -{ - return; - shh::Message m; - m.setTo(stringToPublic(ui->shhTo->currentText())); - m.setPayload(parseData(ui->shhData->toPlainText().toStdString())); - Public f = stringToPublic(ui->shhFrom->currentText()); - Secret from; - if (m_server->ids().count(f)) - from = m_server->ids().at(f); - whisper()->inject(m.seal(from, topicFromText(ui->shhTopic->toPlainText()), ui->shhTtl->value(), ui->shhWork->value())); -} - int Main::authenticate(QString _title, QString _text) { QMessageBox userInput(this); @@ -2318,36 +2188,6 @@ int Main::authenticate(QString _title, QString _text) return userInput.exec(); } -void Main::refreshWhispers() -{ - return; - ui->whispers->clear(); - for (auto const& w: whisper()->all()) - { - shh::Envelope const& e = w.second; - shh::Message m; - for (pair const& i: m_server->ids()) - if (!!(m = e.open(shh::Topics(), i.second))) - break; - if (!m) - m = e.open(shh::Topics()); - - QString msg; - if (m.from()) - // Good message. - msg = QString("{%1 -> %2} %3").arg(m.from() ? m.from().abridged().c_str() : "???").arg(m.to() ? m.to().abridged().c_str() : "*").arg(toHex(m.payload()).c_str()); - else if (m) - // Maybe message. - msg = QString("{%1 -> %2} %3 (?)").arg(m.from() ? m.from().abridged().c_str() : "???").arg(m.to() ? m.to().abridged().c_str() : "*").arg(toHex(m.payload()).c_str()); - - time_t ex = e.expiry(); - QString t(ctime(&ex)); - t.chop(1); - QString item = QString("[%1 - %2s] *%3 %5 %4").arg(t).arg(e.ttl()).arg(e.workProved()).arg(toString(e.topic()).c_str()).arg(msg); - ui->whispers->addItem(item); - } -} - void Main::dappLoaded(Dapp& _dapp) { QUrl url = m_dappHost->hostDapp(std::move(_dapp)); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index e02fb5f4a..ef4e81056 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -84,6 +84,7 @@ public: ~Main(); WebThreeDirect* web3() const override { return m_webThree.get(); } + OurWebThreeStubServer* web3Server() const override { return m_server.get(); } eth::Client* ethereum() const override { return m_webThree->ethereum(); } std::shared_ptr whisper() const override { return m_webThree->whisper(); } @@ -96,8 +97,6 @@ public: std::pair fromString(std::string const& _a) const override; std::string renderDiff(eth::StateDiff const& _d) const override; - QList owned() const { return m_myIdentities; } - u256 gasPrice() const override; eth::KeyManager& keyManager() override { return m_keyManager; } @@ -199,17 +198,11 @@ private slots: void on_debugDumpStatePre_triggered() { debugDumpState(0); } void on_dumpBlockState_triggered(); - // Whisper - void on_newIdentity_triggered(); - void on_post_clicked(); - // Config void on_gasPrices_triggered(); void on_sentinel_triggered(); - void refreshWhisper(); void refreshBlockChain(); - void addNewId(QString _ids); // Dapps void dappLoaded(Dapp& _dapp); //qt does not support rvalue refs for signals @@ -259,7 +252,6 @@ private: void refreshNetwork(); void refreshMining(); - void refreshWhispers(); void refreshCache(); void refreshAll(); @@ -281,7 +273,6 @@ private: QByteArray m_networkConfig; QStringList m_servers; - QList m_myIdentities; eth::KeyManager m_keyManager; QString m_privateChain; dev::Address m_nameReg; diff --git a/alethzero/OurWebThreeStubServer.cpp b/alethzero/OurWebThreeStubServer.cpp index 0eea40c2c..1015e565c 100644 --- a/alethzero/OurWebThreeStubServer.cpp +++ b/alethzero/OurWebThreeStubServer.cpp @@ -34,7 +34,7 @@ OurWebThreeStubServer::OurWebThreeStubServer( jsonrpc::AbstractServerConnector& _conn, Main* _main ): - WebThreeStubServer(_conn, *_main->web3(), make_shared(_main), _main->owned().toVector().toStdVector(), _main->keyManager(), *static_cast(_main->ethereum()->gasPricer().get())), + WebThreeStubServer(_conn, *_main->web3(), make_shared(_main), vector{}, _main->keyManager(), *static_cast(_main->ethereum()->gasPricer().get())), m_main(_main) { } diff --git a/alethzero/plugins/whisper/Whisper.cpp b/alethzero/plugins/whisper/Whisper.cpp new file mode 100644 index 000000000..f3cb38c8e --- /dev/null +++ b/alethzero/plugins/whisper/Whisper.cpp @@ -0,0 +1,177 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file Whisper.cpp + * @author Gav Wood + * @date 2015 + */ + +#include "Whisper.h" +#include +#include +#include +#include +#include +#include "OurWebThreeStubServer.h" +#include "ui_Whisper.h" +using namespace std; +using namespace dev; +using namespace az; +using namespace eth; + +DEV_AZ_NOTE_PLUGIN(Whisper); + +static Public stringToPublic(QString const& _a) +{ + string sn = _a.toStdString(); + if (_a.size() == sizeof(Public) * 2) + return Public(fromHex(_a.toStdString())); + else if (_a.size() == sizeof(Public) * 2 + 2 && _a.startsWith("0x")) + return Public(fromHex(_a.mid(2).toStdString())); + else + return Public(); +} + +static shh::Topics topicFromText(QString _s) +{ + shh::BuildTopic ret; + while (_s.size()) + { + QRegExp r("(@|\\$)?\"([^\"]*)\"(\\s.*)?"); + QRegExp d("(@|\\$)?([0-9]+)(\\s*(ether)|(finney)|(szabo))?(\\s.*)?"); + QRegExp h("(@|\\$)?(0x)?(([a-fA-F0-9])+)(\\s.*)?"); + bytes part; + if (r.exactMatch(_s)) + { + for (auto i: r.cap(2)) + part.push_back((byte)i.toLatin1()); + if (r.cap(1) != "$") + for (int i = r.cap(2).size(); i < 32; ++i) + part.push_back(0); + else + part.push_back(0); + _s = r.cap(3); + } + else if (d.exactMatch(_s)) + { + u256 v(d.cap(2).toStdString()); + if (d.cap(6) == "szabo") + v *= szabo; + else if (d.cap(5) == "finney") + v *= finney; + else if (d.cap(4) == "ether") + v *= ether; + bytes bs = dev::toCompactBigEndian(v); + if (d.cap(1) != "$") + for (auto i = bs.size(); i < 32; ++i) + part.push_back(0); + for (auto b: bs) + part.push_back(b); + _s = d.cap(7); + } + else if (h.exactMatch(_s)) + { + bytes bs = fromHex((((h.cap(3).size() & 1) ? "0" : "") + h.cap(3)).toStdString()); + if (h.cap(1) != "$") + for (auto i = bs.size(); i < 32; ++i) + part.push_back(0); + for (auto b: bs) + part.push_back(b); + _s = h.cap(5); + } + else + _s = _s.mid(1); + ret.shift(part); + } + return ret; +} + + +Whisper::Whisper(MainFace* _m): + Plugin(_m, "Whisper"), + m_ui(new Ui::Whisper) +{ + dock(Qt::RightDockWidgetArea, "Whisper")->setWidget(new QWidget); + m_ui->setupUi(dock()->widget()); + connect(addMenuItem("New Whisper identity.", "menuNetwork", true), &QAction::triggered, this, &Whisper::on_newIdentity_triggered); + connect(_m->web3Server(), &OurWebThreeStubServer::onNewId, this, &Whisper::addNewId); +} + +void Whisper::readSettings(QSettings const& _s) +{ + m_myIdentities.clear(); + QByteArray b = _s.value("identities").toByteArray(); + if (!b.isEmpty()) + { + Secret k; + for (unsigned i = 0; i < b.size() / sizeof(Secret); ++i) + { + memcpy(k.writable().data(), b.data() + i * sizeof(Secret), sizeof(Secret)); + if (!count(m_myIdentities.begin(), m_myIdentities.end(), KeyPair(k))) + m_myIdentities.append(KeyPair(k)); + } + } + main()->web3Server()->setIdentities(keysAsVector(m_myIdentities)); +} + +void Whisper::writeSettings(QSettings& _s) +{ + QByteArray b; + b.resize(sizeof(Secret) * m_myIdentities.size()); + auto p = b.data(); + for (auto i: m_myIdentities) + { + memcpy(p, &(i.secret()), sizeof(Secret)); + p += sizeof(Secret); + } + _s.setValue("identities", b); +} + +void Whisper::addNewId(QString _ids) +{ + KeyPair kp(jsToSecret(_ids.toStdString())); + m_myIdentities.push_back(kp); + main()->web3Server()->setIdentities(keysAsVector(m_myIdentities)); + refreshWhisper(); +} + +void Whisper::refreshWhisper() +{ + m_ui->shhFrom->clear(); + for (auto i: main()->web3Server()->ids()) + m_ui->shhFrom->addItem(QString::fromStdString(toHex(i.first.ref()))); +} + +void Whisper::on_newIdentity_triggered() +{ + KeyPair kp = KeyPair::create(); + m_myIdentities.append(kp); + main()->web3Server()->setIdentities(keysAsVector(m_myIdentities)); + refreshWhisper(); +} + +void Whisper::on_post_clicked() +{ + return; + shh::Message m; + m.setTo(stringToPublic(m_ui->shhTo->currentText())); + m.setPayload(parseData(m_ui->shhData->toPlainText().toStdString())); + Public f = stringToPublic(m_ui->shhFrom->currentText()); + Secret from; + if (main()->web3Server()->ids().count(f)) + from = main()->web3Server()->ids().at(f); + whisper()->inject(m.seal(from, topicFromText(m_ui->shhTopic->toPlainText()), m_ui->shhTtl->value(), m_ui->shhWork->value())); +} diff --git a/alethzero/plugins/whisper/Whisper.h b/alethzero/plugins/whisper/Whisper.h new file mode 100644 index 000000000..bcc1d16df --- /dev/null +++ b/alethzero/plugins/whisper/Whisper.h @@ -0,0 +1,60 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file Whisper.h + * @author Gav Wood + * @date 2015 + */ + +#pragma once + +#include +#include +#include +#include +#include "MainFace.h" + +namespace Ui +{ +class Whisper; +} + +namespace dev +{ +namespace az +{ + +class Whisper: public QObject, public Plugin +{ + Q_OBJECT + +public: + Whisper(MainFace* _m); + +private: + void readSettings(QSettings const&) override; + void writeSettings(QSettings&) override; + void refreshWhisper(); + void addNewId(QString _ids); + void on_newIdentity_triggered(); + void on_post_clicked(); + + Ui::Whisper* m_ui; + QList m_myIdentities; +}; + +} +} diff --git a/alethzero/plugins/whisper/Whisper.ui b/alethzero/plugins/whisper/Whisper.ui new file mode 100644 index 000000000..e143c2f93 --- /dev/null +++ b/alethzero/plugins/whisper/Whisper.ui @@ -0,0 +1,176 @@ + + + Whisper + + + + + + + 0 + 0 + + + + Data + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Work to Prove + + + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + 0 + + + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + 0 + + + + + + + false + + + + + + + + 0 + 0 + + + + Topic + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + To + + + + + + + true + + + + + + + seconds + + + 5 + + + 259200 + + + + + + + + 0 + 0 + + + + TTL + + + + + + + + 0 + 0 + + + + From + + + + + + + ms + + + 1 + + + 1000 + + + 50 + + + + + + + Post + + + + + + + + diff --git a/alethzero/plugins/whisper/WhisperPeers.cpp b/alethzero/plugins/whisper/WhisperPeers.cpp new file mode 100644 index 000000000..07198f93d --- /dev/null +++ b/alethzero/plugins/whisper/WhisperPeers.cpp @@ -0,0 +1,78 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file WhisperPeers.cpp + * @author Gav Wood + * @date 2015 + */ + +#include "WhisperPeers.h" +#include +#include +#include +#include +#include "OurWebThreeStubServer.h" +#include "ui_WhisperPeers.h" +using namespace std; +using namespace dev; +using namespace az; +using namespace eth; + +DEV_AZ_NOTE_PLUGIN(WhisperPeers); + +WhisperPeers::WhisperPeers(MainFace* _m): + Plugin(_m, "WhisperPeers"), + m_ui(new Ui::WhisperPeers) +{ + dock(Qt::RightDockWidgetArea, "Active Whispers")->setWidget(new QWidget); + m_ui->setupUi(dock()->widget()); + startTimer(1000); +} + +void WhisperPeers::timerEvent(QTimerEvent*) +{ + refreshWhispers(); +} + +void WhisperPeers::refreshWhispers() +{ + return; + m_ui->whispers->clear(); + for (auto const& w: whisper()->all()) + { + shh::Envelope const& e = w.second; + shh::Message m; + for (pair const& i: main()->web3Server()->ids()) + if (!!(m = e.open(shh::Topics(), i.second))) + break; + if (!m) + m = e.open(shh::Topics()); + + QString msg; + if (m.from()) + // Good message. + msg = QString("{%1 -> %2} %3").arg(m.from() ? m.from().abridged().c_str() : "???").arg(m.to() ? m.to().abridged().c_str() : "*").arg(toHex(m.payload()).c_str()); + else if (m) + // Maybe message. + msg = QString("{%1 -> %2} %3 (?)").arg(m.from() ? m.from().abridged().c_str() : "???").arg(m.to() ? m.to().abridged().c_str() : "*").arg(toHex(m.payload()).c_str()); + + time_t ex = e.expiry(); + QString t(ctime(&ex)); + t.chop(1); + QString item = QString("[%1 - %2s] *%3 %5 %4").arg(t).arg(e.ttl()).arg(e.workProved()).arg(toString(e.topic()).c_str()).arg(msg); + m_ui->whispers->addItem(item); + } +} diff --git a/alethzero/plugins/whisper/WhisperPeers.h b/alethzero/plugins/whisper/WhisperPeers.h new file mode 100644 index 000000000..2e9ade3a2 --- /dev/null +++ b/alethzero/plugins/whisper/WhisperPeers.h @@ -0,0 +1,55 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file WhisperPeers.h + * @author Gav Wood + * @date 2015 + */ + +#pragma once + +#include +#include +#include +#include +#include "MainFace.h" + +namespace Ui +{ +class WhisperPeers; +} + +namespace dev +{ +namespace az +{ + +class WhisperPeers: public QObject, public Plugin +{ + Q_OBJECT + +public: + WhisperPeers(MainFace* _m); + +private: + void timerEvent(QTimerEvent*) override; + void refreshWhispers(); + + Ui::WhisperPeers* m_ui; +}; + +} +} diff --git a/alethzero/plugins/whisper/WhisperPeers.ui b/alethzero/plugins/whisper/WhisperPeers.ui new file mode 100644 index 000000000..d73c215e8 --- /dev/null +++ b/alethzero/plugins/whisper/WhisperPeers.ui @@ -0,0 +1,32 @@ + + + WhisperPeers + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + + + + + + From 7ad46c546f8531fd83797dd9120756b9caf82931 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 13 Aug 2015 16:11:32 +0200 Subject: [PATCH 39/41] dropped whisper menu --- alethzero/Main.ui | 6 ------ 1 file changed, 6 deletions(-) diff --git a/alethzero/Main.ui b/alethzero/Main.ui index 95f25b694..fe3eadb16 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -210,11 +210,6 @@ - - - &Whisper - - &Debug @@ -235,7 +230,6 @@ - From 36752520529efad4ceaa1fbdc2d7ee8d9b484371 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 13 Aug 2015 16:41:45 +0200 Subject: [PATCH 40/41] moved plugins to subdirs --- alethzero/CMakeLists.txt | 5 +---- alethzero/{ => plugins/blockchain}/AllAccounts.cpp | 0 alethzero/{ => plugins/blockchain}/AllAccounts.h | 0 alethzero/{ => plugins/blockchain}/AllAccounts.ui | 0 alethzero/{ => plugins/brainwallet}/BrainWallet.cpp | 0 alethzero/{ => plugins/brainwallet}/BrainWallet.h | 0 alethzero/{ => plugins/brainwallet}/BrainWallet.ui | 0 alethzero/{ => plugins/log}/LogPanel.cpp | 0 alethzero/{ => plugins/log}/LogPanel.h | 0 alethzero/{ => plugins/log}/LogPanel.ui | 0 alethzero/{ => plugins/namers}/NameRegNamer.cpp | 0 alethzero/{ => plugins/namers}/NameRegNamer.h | 0 alethzero/{ => plugins/namers}/OtherAccounts.cpp | 0 alethzero/{ => plugins/namers}/OtherAccounts.h | 0 alethzero/{ => plugins/namers}/OtherAccounts.ui | 0 alethzero/{ => plugins/namers}/OurAccounts.cpp | 0 alethzero/{ => plugins/namers}/OurAccounts.h | 0 17 files changed, 1 insertion(+), 4 deletions(-) rename alethzero/{ => plugins/blockchain}/AllAccounts.cpp (100%) rename alethzero/{ => plugins/blockchain}/AllAccounts.h (100%) rename alethzero/{ => plugins/blockchain}/AllAccounts.ui (100%) rename alethzero/{ => plugins/brainwallet}/BrainWallet.cpp (100%) rename alethzero/{ => plugins/brainwallet}/BrainWallet.h (100%) rename alethzero/{ => plugins/brainwallet}/BrainWallet.ui (100%) rename alethzero/{ => plugins/log}/LogPanel.cpp (100%) rename alethzero/{ => plugins/log}/LogPanel.h (100%) rename alethzero/{ => plugins/log}/LogPanel.ui (100%) rename alethzero/{ => plugins/namers}/NameRegNamer.cpp (100%) rename alethzero/{ => plugins/namers}/NameRegNamer.h (100%) rename alethzero/{ => plugins/namers}/OtherAccounts.cpp (100%) rename alethzero/{ => plugins/namers}/OtherAccounts.h (100%) rename alethzero/{ => plugins/namers}/OtherAccounts.ui (100%) rename alethzero/{ => plugins/namers}/OurAccounts.cpp (100%) rename alethzero/{ => plugins/namers}/OurAccounts.h (100%) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 045b6042d..984b8553d 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -49,9 +49,6 @@ qt5_wrap_ui(ui_GasPricing.h GasPricing.ui) # Extensions qt5_wrap_ui(ui_AllAccounts.h AllAccounts.ui) -qt5_wrap_ui(ui_LogPanel.h LogPanel.ui) -qt5_wrap_ui(ui_BrainWallet.h BrainWallet.ui) -qt5_wrap_ui(ui_OtherAccounts.h OtherAccounts.ui) file(GLOB HEADERS "*.h") @@ -64,7 +61,7 @@ endif () # eth_add_executable is defined in cmake/EthExecutableHelper.cmake eth_add_executable(${EXECUTABLE} ICON alethzero - UI_RESOURCES ${PLUGIN_UI} alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui ExportState.ui GetPassword.ui GasPricing.ui AllAccounts.ui LogPanel.ui BrainWallet.ui OtherAccounts.ui + UI_RESOURCES ${PLUGIN_UI} alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui ExportState.ui GetPassword.ui GasPricing.ui WIN_RESOURCES alethzero.rc ) diff --git a/alethzero/AllAccounts.cpp b/alethzero/plugins/blockchain/AllAccounts.cpp similarity index 100% rename from alethzero/AllAccounts.cpp rename to alethzero/plugins/blockchain/AllAccounts.cpp diff --git a/alethzero/AllAccounts.h b/alethzero/plugins/blockchain/AllAccounts.h similarity index 100% rename from alethzero/AllAccounts.h rename to alethzero/plugins/blockchain/AllAccounts.h diff --git a/alethzero/AllAccounts.ui b/alethzero/plugins/blockchain/AllAccounts.ui similarity index 100% rename from alethzero/AllAccounts.ui rename to alethzero/plugins/blockchain/AllAccounts.ui diff --git a/alethzero/BrainWallet.cpp b/alethzero/plugins/brainwallet/BrainWallet.cpp similarity index 100% rename from alethzero/BrainWallet.cpp rename to alethzero/plugins/brainwallet/BrainWallet.cpp diff --git a/alethzero/BrainWallet.h b/alethzero/plugins/brainwallet/BrainWallet.h similarity index 100% rename from alethzero/BrainWallet.h rename to alethzero/plugins/brainwallet/BrainWallet.h diff --git a/alethzero/BrainWallet.ui b/alethzero/plugins/brainwallet/BrainWallet.ui similarity index 100% rename from alethzero/BrainWallet.ui rename to alethzero/plugins/brainwallet/BrainWallet.ui diff --git a/alethzero/LogPanel.cpp b/alethzero/plugins/log/LogPanel.cpp similarity index 100% rename from alethzero/LogPanel.cpp rename to alethzero/plugins/log/LogPanel.cpp diff --git a/alethzero/LogPanel.h b/alethzero/plugins/log/LogPanel.h similarity index 100% rename from alethzero/LogPanel.h rename to alethzero/plugins/log/LogPanel.h diff --git a/alethzero/LogPanel.ui b/alethzero/plugins/log/LogPanel.ui similarity index 100% rename from alethzero/LogPanel.ui rename to alethzero/plugins/log/LogPanel.ui diff --git a/alethzero/NameRegNamer.cpp b/alethzero/plugins/namers/NameRegNamer.cpp similarity index 100% rename from alethzero/NameRegNamer.cpp rename to alethzero/plugins/namers/NameRegNamer.cpp diff --git a/alethzero/NameRegNamer.h b/alethzero/plugins/namers/NameRegNamer.h similarity index 100% rename from alethzero/NameRegNamer.h rename to alethzero/plugins/namers/NameRegNamer.h diff --git a/alethzero/OtherAccounts.cpp b/alethzero/plugins/namers/OtherAccounts.cpp similarity index 100% rename from alethzero/OtherAccounts.cpp rename to alethzero/plugins/namers/OtherAccounts.cpp diff --git a/alethzero/OtherAccounts.h b/alethzero/plugins/namers/OtherAccounts.h similarity index 100% rename from alethzero/OtherAccounts.h rename to alethzero/plugins/namers/OtherAccounts.h diff --git a/alethzero/OtherAccounts.ui b/alethzero/plugins/namers/OtherAccounts.ui similarity index 100% rename from alethzero/OtherAccounts.ui rename to alethzero/plugins/namers/OtherAccounts.ui diff --git a/alethzero/OurAccounts.cpp b/alethzero/plugins/namers/OurAccounts.cpp similarity index 100% rename from alethzero/OurAccounts.cpp rename to alethzero/plugins/namers/OurAccounts.cpp diff --git a/alethzero/OurAccounts.h b/alethzero/plugins/namers/OurAccounts.h similarity index 100% rename from alethzero/OurAccounts.h rename to alethzero/plugins/namers/OurAccounts.h From 225e2b9330945a2917326adbad33235742b373d9 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 13 Aug 2015 17:14:11 +0200 Subject: [PATCH 41/41] refresh on settigs load --- alethzero/CMakeLists.txt | 1 - alethzero/plugins/whisper/Whisper.cpp | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 984b8553d..e4dfabc5f 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -16,7 +16,6 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) file(GLOB_RECURSE SRC_LIST "./plugins/*.cpp") file(GLOB_RECURSE HEADERS "./plugins/*.h") -file(GLOB_RECURSE PLUGIN_UI "./plugins/*.ui") aux_source_directory(. SRC_LIST) file(GLOB_RECURSE PLUGIN_UI RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/plugins/*.ui") diff --git a/alethzero/plugins/whisper/Whisper.cpp b/alethzero/plugins/whisper/Whisper.cpp index f3cb38c8e..cb5d9908f 100644 --- a/alethzero/plugins/whisper/Whisper.cpp +++ b/alethzero/plugins/whisper/Whisper.cpp @@ -125,6 +125,7 @@ void Whisper::readSettings(QSettings const& _s) } } main()->web3Server()->setIdentities(keysAsVector(m_myIdentities)); + refreshWhisper(); } void Whisper::writeSettings(QSettings& _s)