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/69] 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/69] 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/69] 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/69] 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/69] 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/69] 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/69] 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/69] 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/69] 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/69] 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/69] 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/69] 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/69] 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/69] 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/69] 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/69] 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/69] 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 19c9ae935a8d93a37ad78c0ade494e355f39c657 Mon Sep 17 00:00:00 2001 From: subtly Date: Fri, 7 Aug 2015 21:16:53 +0200 Subject: [PATCH 18/69] --peerset CLI option for required (static) peers --- eth/main.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++---- libp2p/Host.h | 10 ------- libp2p/Network.h | 4 ++- 3 files changed, 75 insertions(+), 17 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 371c54c04..b2425ba31 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -181,11 +181,12 @@ void help() << " --network-id Only connect to other hosts with this network id." << endl << " --upnp Use UPnP for NAT (default: on)." << endl -// << " --peers Text list of type publickey@host[:port] (default: network)" << endl -// << " Types:" << endl -// << " default Attempt connection when no other peers are available and pinning is disable." << endl -// << " trusted Keep connected at all times." << endl -// << " --trust-peers Text list of publickeys." << endl + << " --peerset Space delimited list of type type:publickey@ipAddress[:port]" << endl + << " Types:" << endl + << " default Attempt connection when no other peers are available and pinning is disable." << endl + << " require Keep connected at all times." << endl +// TODO: +// << " --trust-peers Space delimited list of publickeys." << endl << " --no-discovery Disable Node discovery." << endl << " --pin Only accept or connect to trusted peers." << endl @@ -359,6 +360,7 @@ int main(int argc, char** argv) HostPeerPreferences hprefs; unsigned peers = hprefs.idealPeerCount; unsigned peerStretch = hprefs.stretchPeerCount; + std::map preferredNodes; bool bootstrap = false; bool disableDiscovery = false; bool pinning = false; @@ -717,6 +719,63 @@ int main(int argc, char** argv) peers = atoi(argv[++i]); else if (arg == "--peer-stretch" && i + 1 < argc) peerStretch = atoi(argv[++i]); + else if (arg == "--peerset" && i + 1 < argc) + { + string peerset = argv[++i]; + if (peerset.empty()) + { + cerr << "--peerset argument must not be empty"; + return -1; + } + + vector each; + boost::split(strs, peerset, boost::is_any_of("\t ")); + for (auto const& p: each) + { + string type; + string pubk; + string hostIP; + unsigned short port = c_defaultListenPort; + + // type:key@ip[:port] + vector typeAndKeyAtHostAndPort; + boost::split(typeAndKeyAtHostAndPort, peerset, boost::is_any_of(":")); + if (typeAndKeyAtHostAndPort.size() < 2 || typeAndKeyAtHostAndPort.size() > 3) + continue; + + type = typeAndKeyAtHostAndPort[0]; + if (typeAndKeyAtHostAndPort.size() == 3) + port = (uint16_t)atoi(typeAndKeyAtHostAndPort[2].c_str()); + + vector keyAndHost; + boost::split(keyAndHost, typeAndKeyAtHostAndPort[1], boost::is_any_of("@")); + if (keyAndHost.size() != 2) + continue; + pubk = keyAndHost[0]; + if (pubk.size() != 40) + continue; + hostIP = keyAndHost[1]; + + // todo: use Network::resolveHost() + if (hostIP.size() < 4 /* g.it */) + continue; + + bool required = type == "required"; + if (!required && type != "default") + continue; + + Public publicKey(fromHex(pubk)); + try + { + preferredNodes[publicKey] = Node(pubk, NodeIPEndpoint(bi::address(hostIP), port, port), required); + } + catch (...) + { + cerr << "Unrecognized peerset: " << peerset << endl; + return -1; + } + } + } else if ((arg == "-o" || arg == "--mode") && i + 1 < argc) { string m = argv[++i]; @@ -1002,6 +1061,7 @@ int main(int argc, char** argv) } cout << ethCredits(); + web3.setIdealPeerCount(peers); web3.setPeerStretch(peerStretch); // std::shared_ptr gasPricer = make_shared(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000)); @@ -1051,12 +1111,18 @@ int main(int argc, char** argv) } #endif + for (auto const& p: preferredNodes) + if (p.second.required) + web3.requirePeer(p.first, p.second.endpoint); + else + web3.addNode(p.first, p.second.endpoint); + if (bootstrap) for (auto const& i: Host::pocHosts()) web3.requirePeer(i.first, i.second); if (!remoteHost.empty()) web3.addNode(p2p::NodeId(), remoteHost + ":" + toString(remotePort)); - + signal(SIGABRT, &sighandler); signal(SIGTERM, &sighandler); signal(SIGINT, &sighandler); diff --git a/libp2p/Host.h b/libp2p/Host.h index 863149899..31eac5319 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -119,16 +119,6 @@ struct NodeInfo std::string version; }; -struct HostPeerPreferences -{ - unsigned const idealPeerCount = 11; // Ideal number of peers to be connected to. - unsigned const stretchPeerCount = 7; // Accepted connection multiplier (max peers = ideal*stretch). - -// std::list const defaultPeers; -// std::list const requiredPeers; -// std::list const trusted; -}; - /** * @brief The Host class * Capabilities should be registered prior to startNetwork, since m_capabilities is not thread-safe. diff --git a/libp2p/Network.h b/libp2p/Network.h index 3b4396510..c9c62aace 100644 --- a/libp2p/Network.h +++ b/libp2p/Network.h @@ -37,6 +37,8 @@ namespace dev namespace p2p { +static const unsigned short c_defaultListenPort = 30303; + struct NetworkPreferences { // Default Network Preferences @@ -52,7 +54,7 @@ struct NetworkPreferences std::string publicIPAddress; std::string listenIPAddress; - unsigned short listenPort = 30303; + unsigned short listenPort = c_defaultListenPort; /// Preferences From 63db0ca037499752533eefcbf687a37bd835fe18 Mon Sep 17 00:00:00 2001 From: subtly Date: Fri, 7 Aug 2015 21:22:09 +0200 Subject: [PATCH 19/69] ws --- eth/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/eth/main.cpp b/eth/main.cpp index e8705bcd0..e098db5ff 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -1061,7 +1061,6 @@ int main(int argc, char** argv) } cout << ethCredits(); - web3.setIdealPeerCount(peers); web3.setPeerStretch(peerStretch); // std::shared_ptr gasPricer = make_shared(u256(double(ether / 1000) / etherPrice), u256(blockFees * 1000)); From 479bfc6d54626c83fa402b675f60253ca5f2aa53 Mon Sep 17 00:00:00 2001 From: subtly Date: Fri, 7 Aug 2015 22:38:08 +0200 Subject: [PATCH 20/69] fix --- eth/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index e098db5ff..af997f333 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -729,7 +729,7 @@ int main(int argc, char** argv) } vector each; - boost::split(strs, peerset, boost::is_any_of("\t ")); + boost::split(each, peerset, boost::is_any_of("\t ")); for (auto const& p: each) { string type; @@ -739,7 +739,7 @@ int main(int argc, char** argv) // type:key@ip[:port] vector typeAndKeyAtHostAndPort; - boost::split(typeAndKeyAtHostAndPort, peerset, boost::is_any_of(":")); + boost::split(typeAndKeyAtHostAndPort, p, boost::is_any_of(":")); if (typeAndKeyAtHostAndPort.size() < 2 || typeAndKeyAtHostAndPort.size() > 3) continue; From 7186460b57cbc6ee3b947e8f87bd122448638c88 Mon Sep 17 00:00:00 2001 From: subtly Date: Fri, 7 Aug 2015 23:20:55 +0200 Subject: [PATCH 21/69] removed HostPeerPrefs --- eth/main.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index af997f333..66f04f815 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -357,9 +357,8 @@ int main(int argc, char** argv) string remoteHost; unsigned short remotePort = 30303; - HostPeerPreferences hprefs; - unsigned peers = hprefs.idealPeerCount; - unsigned peerStretch = hprefs.stretchPeerCount; + unsigned peers = 11; + unsigned peerStretch = 7; std::map preferredNodes; bool bootstrap = false; bool disableDiscovery = false; From 4d380c7a2d29ace7bab0ec88ae8edff914dfa2a2 Mon Sep 17 00:00:00 2001 From: subtly Date: Sat, 8 Aug 2015 18:05:12 +0200 Subject: [PATCH 22/69] Don't use Node, as can't be copioed. --- eth/main.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index 66f04f815..fc60220f2 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -359,7 +359,7 @@ int main(int argc, char** argv) unsigned peers = 11; unsigned peerStretch = 7; - std::map preferredNodes; + std::map> preferredNodes; bool bootstrap = false; bool disableDiscovery = false; bool pinning = false; @@ -766,7 +766,7 @@ int main(int argc, char** argv) Public publicKey(fromHex(pubk)); try { - preferredNodes[publicKey] = Node(pubk, NodeIPEndpoint(bi::address(hostIP), port, port), required); + preferredNodes[publicKey] = make_pair(NodeIPEndpoint(bi::address::from_string(hostIP), port, port), required); } catch (...) { @@ -1110,10 +1110,10 @@ int main(int argc, char** argv) #endif for (auto const& p: preferredNodes) - if (p.second.required) - web3.requirePeer(p.first, p.second.endpoint); + if (p.second.second) + web3.requirePeer(p.first, p.second.first); else - web3.addNode(p.first, p.second.endpoint); + web3.addNode(p.first, p.second.first); if (bootstrap) for (auto const& i: Host::pocHosts()) From 6d33f2ff9ba4098e295f6a08b7282c2e2698b435 Mon Sep 17 00:00:00 2001 From: subtly Date: Mon, 10 Aug 2015 15:24:11 +0200 Subject: [PATCH 23/69] whitespace in cli options --- eth/main.cpp | 12 ++++++------ libp2p/Host.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index fc60220f2..77695f652 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -171,9 +171,9 @@ void help() << " --client-name Add a name to your client's version string (default: blank)." << endl << " -b,--bootstrap Connect to the default Ethereum peerserver." << endl << " -x,--peers Attempt to connect to given number of peers (default: 11)." << endl - << " --peer-stretch Accepted connection multiplier (default: 7)." << endl + << " --peer-stretch Accepted connection multiplier (default: 7)." << endl - << " --public-ip Force public ip to given (default: auto)." << endl + << " --public-ip Force advertised public ip to given (default: auto)." << endl << " --listen-ip (:) Listen on the given IP for incoming connections (default: 0.0.0.0)." << endl << " --listen Listen on the given port for incoming connections (default: 30303)." << endl << " -r,--remote (:) Connect to remote host (default: none)." << endl @@ -181,10 +181,10 @@ void help() << " --network-id Only connect to other hosts with this network id." << endl << " --upnp Use UPnP for NAT (default: on)." << endl - << " --peerset Space delimited list of type type:publickey@ipAddress[:port]" << endl - << " Types:" << endl - << " default Attempt connection when no other peers are available and pinning is disable." << endl - << " require Keep connected at all times." << endl + << " --peerset Space delimited list of type type:publickey@ipAddress[:port]" << endl + << " Types:" << endl + << " default Attempt connection when no other peers are available and pinning is disable." << endl + << " require Keep connected at all times." << endl // TODO: // << " --trust-peers Space delimited list of publickeys." << endl diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 64d10b172..7fd98cac8 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -449,7 +449,7 @@ string Host::pocHost() std::unordered_map const& Host::pocHosts() { static const std::unordered_map c_ret = { - { Public("487611428e6c99a11a9795a6abe7b529e81315ca6aad66e2a2fc76e3adf263faba0d35466c2f8f68d561dbefa8878d4df5f1f2ddb1fbeab7f42ffb8cd328bd4a"), "poc-9.ethdev.com:30303" }, + { Public("979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9"), "poc-9.ethdev.com:30303" }, { Public("a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c"), "52.16.188.185:30303" }, { Public("7f25d3eab333a6b98a8b5ed68d962bb22c876ffcd5561fca54e3c2ef27f754df6f7fd7c9b74cc919067abac154fb8e1f8385505954f161ae440abc355855e034"), "54.207.93.166:30303" } }; 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 24/69] 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 25/69] 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 1de4b2cd8f31de6ea417c49aeadc83a0ef935baa Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 11 Aug 2015 13:54:43 +0200 Subject: [PATCH 26/69] Wording for MIT license and external contributors --- LICENSE => GPLV3_LICENSE | 0 LICENCE | 21 +++++++++++++++++++++ README.md | 12 +++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) rename LICENSE => GPLV3_LICENSE (100%) create mode 100644 LICENCE diff --git a/LICENSE b/GPLV3_LICENSE similarity index 100% rename from LICENSE rename to GPLV3_LICENSE diff --git a/LICENCE b/LICENCE new file mode 100644 index 000000000..c42a6c8e9 --- /dev/null +++ b/LICENCE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md index 1446e14da..f79257a15 100644 --- a/README.md +++ b/README.md @@ -43,10 +43,20 @@ See [TODO](https://github.com/ethereum/cpp-ethereum/wiki/TODO) ### License -See [LICENSE](LICENSE) +All new contributions are under the [MIT license](http://opensource.org/licenses/MIT). +See [LICENSE](LICENSE). Some old contributions are under the [GPLv3 license](http://www.gnu.org/licenses/gpl-3.0.en.html). See [GPLV3_LICENSE](GPLV3_LICENSE). ### Contributing +All new contributions are added under the MIT License. Please refer to the `LICENCSE` file in the root directory. +To state that you accept this fact for all of your PRs please add yourself to the list of external contributors +like in the example below. + +#### External Contributors +- *Name Surname* (**email@domain**) + +#### Contribution guideline + All development goes in develop branch - please don't submit pull requests to master. Please read [CodingStandards.txt](CodingStandards.txt) thoroughly before making alterations to the code base. Please do *NOT* use an editor that automatically reformats whitespace away from astylerc or the formatting guidelines as described in [CodingStandards.txt](CodingStandards.txt). From 7d37d302f601cbd6239acb61deb4c72037025a60 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 11 Aug 2015 14:12:09 +0200 Subject: [PATCH 27/69] Remind contributors to add to @author --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index f79257a15..fc1effcec 100644 --- a/README.md +++ b/README.md @@ -53,10 +53,15 @@ To state that you accept this fact for all of your PRs please add yourself to th like in the example below. #### External Contributors +I hereby place all my contributions in this file under an MIT +licence, as specified [here](http://opensource.org/licenses/MIT). - *Name Surname* (**email@domain**) #### Contribution guideline +Please add yourself in the `@author` section of the file your are adding/editing +with the same wording as the one you listed yourself in the external contributors section above. + All development goes in develop branch - please don't submit pull requests to master. Please read [CodingStandards.txt](CodingStandards.txt) thoroughly before making alterations to the code base. Please do *NOT* use an editor that automatically reformats whitespace away from astylerc or the formatting guidelines as described in [CodingStandards.txt](CodingStandards.txt). From 0e2753319b0354b7561fcc9a672b4ef9a150482c Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 11 Aug 2015 15:03:57 +0200 Subject: [PATCH 28/69] Some readme disambiguations --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index fc1effcec..09e2ccb39 100644 --- a/README.md +++ b/README.md @@ -48,19 +48,19 @@ See [LICENSE](LICENSE). Some old contributions are under the [GPLv3 license](htt ### Contributing -All new contributions are added under the MIT License. Please refer to the `LICENCSE` file in the root directory. -To state that you accept this fact for all of your PRs please add yourself to the list of external contributors -like in the example below. +All new contributions are added under the MIT License. Please refer to the `LICENSE` file in the root directory. +To state that you accept this fact for all of your contributions please add yourself to the list of external contributors like in the example below. #### External Contributors -I hereby place all my contributions in this file under an MIT +I hereby place all my contributions in this codebase under an MIT licence, as specified [here](http://opensource.org/licenses/MIT). - *Name Surname* (**email@domain**) #### Contribution guideline -Please add yourself in the `@author` section of the file your are adding/editing -with the same wording as the one you listed yourself in the external contributors section above. +Please add yourself in the `@author` doxygen section of the file your are adding/editing +with the same wording as the one you listed yourself in the external contributors section above, +only replacing the word **contribution** by **file** All development goes in develop branch - please don't submit pull requests to master. 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 29/69] 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 68478600092935534dc930caf29ce88e2898cb7a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 12 Aug 2015 13:56:49 +0200 Subject: [PATCH 30/69] Version bump. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ce729917..4c07ab608 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # cmake global cmake_minimum_required(VERSION 2.8.12) -set(PROJECT_VERSION "0.9.40") +set(PROJECT_VERSION "0.9.41") 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() 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 31/69] 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 e9840bdfaf788f1dcb497817a081433a9cdd130e Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 12 Aug 2015 14:40:53 +0200 Subject: [PATCH 32/69] typo in LICENSE file name --- LICENCE => LICENSE | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename LICENCE => LICENSE (100%) diff --git a/LICENCE b/LICENSE similarity index 100% rename from LICENCE rename to LICENSE From 400d61ebdb8543550b653aed926e6160465f9351 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 12 Aug 2015 14:46:52 +0200 Subject: [PATCH 33/69] Trim input before use. --- alethzero/Transact.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index 7e239bc1c..df8787522 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -168,9 +168,9 @@ void Transact::on_destination_currentTextChanged(QString) { pair p; if (!ui->destination->currentData().isNull() && ui->destination->currentText() == ui->destination->itemText(ui->destination->currentIndex())) - p.first = Address(ui->destination->currentData().toString().toStdString()); + p.first = Address(ui->destination->currentData().toString().trimmed().toStdString()); else - p = m_main->fromString(ui->destination->currentText().toStdString()); + p = m_main->fromString(ui->destination->currentText().trimmed().toStdString()); if (p.first) ui->calculatedName->setText(QString::fromStdString(m_main->render(p.first))); 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 34/69] "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 82f4111e0502a2e8f170b6cf3303859b2cca7444 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 12 Aug 2015 15:00:48 +0200 Subject: [PATCH 35/69] Reduce verbosity on status bar. Fixes #2799. --- alethzero/MainWin.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 26dec2345..a78949413 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -177,7 +177,8 @@ Main::Main(QWidget* _parent): ui->configDock->close(); - statusBar()->addPermanentWidget(ui->cacheUsage); +// statusBar()->addPermanentWidget(ui->cacheUsage); + ui->cacheUsage->hide(); statusBar()->addPermanentWidget(ui->balance); statusBar()->addPermanentWidget(ui->peerCount); statusBar()->addPermanentWidget(ui->mineStatus); @@ -185,7 +186,6 @@ Main::Main(QWidget* _parent): statusBar()->addPermanentWidget(ui->chainStatus); statusBar()->addPermanentWidget(ui->blockCount); - QSettings s("ethereum", "alethzero"); m_networkConfig = s.value("peers").toByteArray(); bytesConstRef network((byte*)m_networkConfig.data(), m_networkConfig.size()); @@ -789,7 +789,7 @@ QString Main::lookup(QString const& _a) const void Main::on_about_triggered() { - QMessageBox::about(this, "About AlethZero PoC-" + QString(dev::Version).section('.', 1, 1), QString("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) "\n" DEV_QUOTED(ETH_COMMIT_HASH) + (ETH_CLEAN_REPO ? "\nCLEAN" : "\n+ LOCAL CHANGES") + "\n\nBerlin ÐΞV team, 2014.\nOriginally by Gav Wood. Based on a design by Vitalik Buterin.\n\nThanks to the various contributors including: Tim Hughes, caktux, Eric Lombrozo, Marko Simovic."); + QMessageBox::about(this, "About AlethZero PoC-" + QString(dev::Version).section('.', 1, 1), QString("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM) "\n" DEV_QUOTED(ETH_COMMIT_HASH) + (ETH_CLEAN_REPO ? "\nCLEAN" : "\n+ LOCAL CHANGES") + "\n\nBy Gav Wood and the Berlin ÐΞV team, 2014, 2015.\nSee the README for contributors and credits."); } void Main::on_paranoia_triggered() @@ -1336,7 +1336,6 @@ void Main::refreshPending() void Main::refreshBlockCount() { auto d = ethereum()->blockChain().details(); - BlockQueueStatus b = ethereum()->blockQueueStatus(); SyncStatus sync = ethereum()->syncStatus(); QString syncStatus = QString("PV%1 %2").arg(sync.protocolVersion).arg(EthereumHost::stateName(sync.state)); if (sync.state == SyncState::Hashes) @@ -1344,8 +1343,11 @@ void Main::refreshBlockCount() if (sync.state == SyncState::Blocks || sync.state == SyncState::NewBlocks) syncStatus += QString(": %1/%2").arg(sync.blocksReceived).arg(sync.blocksTotal); ui->syncStatus->setText(syncStatus); - ui->chainStatus->setText(QString("%3 importing %4 ready %5 verifying %6 unverified %7 future %8 unknown %9 bad %1 #%2") - .arg(m_privateChain.size() ? "[" + m_privateChain + "] " : c_network == eth::Network::Olympic ? "Olympic" : "Frontier").arg(d.number).arg(b.importing).arg(b.verified).arg(b.verifying).arg(b.unverified).arg(b.future).arg(b.unknown).arg(b.bad)); +// BlockQueueStatus b = ethereum()->blockQueueStatus(); +// ui->chainStatus->setText(QString("%3 importing %4 ready %5 verifying %6 unverified %7 future %8 unknown %9 bad %1 #%2") +// .arg(m_privateChain.size() ? "[" + m_privateChain + "] " : c_network == eth::Network::Olympic ? "Olympic" : "Frontier").arg(d.number).arg(b.importing).arg(b.verified).arg(b.verifying).arg(b.unverified).arg(b.future).arg(b.unknown).arg(b.bad)); + ui->chainStatus->setText(QString("%1 #%2") + .arg(m_privateChain.size() ? "[" + m_privateChain + "] " : c_network == eth::Network::Olympic ? "Olympic" : "Frontier").arg(d.number)); } void Main::on_turboMining_triggered() From bfc7851d68b87ed3c3e3ba035994c168b5d11325 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 12 Aug 2015 15:20:34 +0200 Subject: [PATCH 36/69] Fix destination address in AlethZero. --- alethzero/Context.cpp | 13 +++++++++---- alethzero/Transact.cpp | 30 ++++++++++++++---------------- alethzero/Transact.h | 2 +- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/alethzero/Context.cpp b/alethzero/Context.cpp index d567c4ee5..c734c06d1 100644 --- a/alethzero/Context.cpp +++ b/alethzero/Context.cpp @@ -39,12 +39,17 @@ Context::~Context() void dev::az::setValueUnits(QComboBox* _units, QSpinBox* _value, u256 _v) { initUnits(_units); - _units->setCurrentIndex(0); - while (_v > 50000 && _units->currentIndex() < (int)(units().size() - 2)) + if (_v > 0) { - _v /= 1000; - _units->setCurrentIndex(_units->currentIndex() + 1); + _units->setCurrentIndex(0); + while (_v > 50000 && _units->currentIndex() < (int)(units().size() - 2)) + { + _v /= 1000; + _units->setCurrentIndex(_units->currentIndex() + 1); + } } + else + _units->setCurrentIndex(6); _value->setValue((unsigned)_v); } diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index df8787522..77058817d 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -121,11 +121,6 @@ u256 Transact::gasPrice() const return ui->gasPrice->value() * units()[units().size() - 1 - ui->gasPriceUnits->currentIndex()].first; } -Address Transact::to() const -{ - return m_main->fromString(ui->destination->currentText().toStdString()).first; -} - u256 Transact::total() const { return value() + fee(); @@ -166,12 +161,7 @@ void Transact::on_destination_currentTextChanged(QString) { if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)") { - pair p; - if (!ui->destination->currentData().isNull() && ui->destination->currentText() == ui->destination->itemText(ui->destination->currentIndex())) - p.first = Address(ui->destination->currentData().toString().trimmed().toStdString()); - else - p = m_main->fromString(ui->destination->currentText().trimmed().toStdString()); - + auto p = toAccount(); if (p.first) ui->calculatedName->setText(QString::fromStdString(m_main->render(p.first))); else @@ -210,7 +200,7 @@ void Transact::on_copyUnsigned_clicked() t = Transaction(value(), gasPrice(), ui->gas->value(), m_data, nonce); else // TODO: cache like m_data. - t = Transaction(value(), gasPrice(), ui->gas->value(), to(), m_data, nonce); + t = Transaction(value(), gasPrice(), ui->gas->value(), toAccount().first, m_data, nonce); qApp->clipboard()->setText(QString::fromStdString(toHex(t.rlp()))); } @@ -331,9 +321,17 @@ string Transact::natspecNotice(Address _to, bytes const& _data) return "Destination not a contract."; } -Address Transact::toAccount() +pair Transact::toAccount() { - return isCreation() ? Address() : m_main->fromString(ui->destination->currentText().toStdString()).first; + pair p; + if (!isCreation()) + { + if (!ui->destination->currentData().isNull() && ui->destination->currentText() == ui->destination->itemText(ui->destination->currentIndex())) + p.first = Address(ui->destination->currentData().toString().trimmed().toStdString()); + else + p = m_main->fromString(ui->destination->currentText().trimmed().toStdString()); + } + return p; } GasRequirements Transact::determineGasRequirements() @@ -342,7 +340,7 @@ GasRequirements Transact::determineGasRequirements() qint64 baseGas = (qint64)Transaction::gasRequired(m_data, 0); Address from = fromAccount(); - Address to = toAccount(); + Address to = toAccount().first; ExecutionResult lastGood; bool haveUpperBound = false; @@ -452,7 +450,7 @@ void Transact::rejigData() // Add Natspec information if (!isCreation()) - htmlInfo = "
INFO " + QString::fromStdString(natspecNotice(toAccount(), m_data)).toHtmlEscaped() + "
" + htmlInfo; + htmlInfo = "
INFO " + QString::fromStdString(natspecNotice(toAccount().first, m_data)).toHtmlEscaped() + "
" + htmlInfo; // Update gas if (ui->gas->value() == ui->gas->minimum()) diff --git a/alethzero/Transact.h b/alethzero/Transact.h index 8b319c912..60d4a3c2e 100644 --- a/alethzero/Transact.h +++ b/alethzero/Transact.h @@ -81,7 +81,7 @@ private: void updateNonce(); dev::Address fromAccount(); - dev::Address toAccount(); + std::pair toAccount(); void updateDestination(); void updateFee(); bool isCreation() const; From 654efb3987865933bfe47f8bde2bc2680efedfc6 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 12 Aug 2015 15:35:00 +0200 Subject: [PATCH 37/69] Fix destination in Transact debugging. --- alethzero/Transact.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index 77058817d..970c2cca0 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -545,7 +545,7 @@ void Transact::on_send_clicked() } else // TODO: cache like m_data. - ethereum()->submitTransaction(s, value(), m_main->fromString(ui->destination->currentText().toStdString()).first, m_data, ui->gas->value(), gasPrice(), nonce); + ethereum()->submitTransaction(s, value(), toAccount().first, m_data, ui->gas->value(), gasPrice(), nonce); close(); } @@ -565,7 +565,7 @@ void Transact::on_debug_clicked() Block postState(ethereum()->postState()); Transaction t = isCreation() ? Transaction(value(), gasPrice(), ui->gas->value(), m_data, postState.transactionsFrom(from)) : - Transaction(value(), gasPrice(), ui->gas->value(), m_main->fromString(ui->destination->currentText().toStdString()).first, m_data, postState.transactionsFrom(from)); + Transaction(value(), gasPrice(), ui->gas->value(), toAccount().first, m_data, postState.transactionsFrom(from)); t.forceSender(from); Debugger dw(m_main, this); Executive e(postState, ethereum()->blockChain(), 0); 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 38/69] 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 bc5196445a09c5eb092e800be8b0ef789ca2f5de Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 12 Aug 2015 16:14:51 +0200 Subject: [PATCH 39/69] fixed transaction creating for a new state --- libethereum/EthereumPeer.cpp | 2 +- mix/ClientModel.cpp | 3 +++ mix/qml/BlockChain.qml | 4 ++-- mix/qml/ScenarioLoader.qml | 3 ++- mix/qml/StructView.qml | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/libethereum/EthereumPeer.cpp b/libethereum/EthereumPeer.cpp index 4450a3d56..947041db9 100644 --- a/libethereum/EthereumPeer.cpp +++ b/libethereum/EthereumPeer.cpp @@ -63,7 +63,7 @@ EthereumPeer::~EthereumPeer() { if (m_asking != Asking::Nothing) { - cnote << "Peer aborting while being asked for " << ::toString(m_asking); + clog(NetAllDetail) << "Peer aborting while being asked for " << ::toString(m_asking); setRude(); } abortSync(); diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 7a51c99f7..7ab6c5858 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -444,7 +444,10 @@ void ClientModel::executeSequence(vector const& _sequence) { auto contractAddressIter = m_contractAddresses.find(ctrInstance); if (contractAddressIter == m_contractAddresses.end()) + { emit runFailed("Contract '" + transaction.contractId + tr(" not deployed.") + "' " + tr(" Cannot call ") + transaction.functionId); + break; + } callAddress(contractAddressIter->second, encoder.encodedData(), transaction); } m_gasCosts.append(m_client->lastExecution().gasUsed); diff --git a/mix/qml/BlockChain.qml b/mix/qml/BlockChain.qml index 69d42799c..e13b871dd 100644 --- a/mix/qml/BlockChain.qml +++ b/mix/qml/BlockChain.qml @@ -492,7 +492,7 @@ ColumnLayout { ScenarioButton { id: addBlockBtn - text: qsTr("Add Block..") + text: qsTr("Add Block...") anchors.left: addTransaction.right roundLeft: false roundRight: true @@ -609,7 +609,7 @@ ColumnLayout { ScenarioButton { id: newAccount - text: qsTr("New Account..") + text: qsTr("New Account...") onClicked: { var ac = projectModel.stateListModel.newAccount("O", QEther.Wei) model.accounts.push(ac) diff --git a/mix/qml/ScenarioLoader.qml b/mix/qml/ScenarioLoader.qml index c4ce19af0..f47296514 100644 --- a/mix/qml/ScenarioLoader.qml +++ b/mix/qml/ScenarioLoader.qml @@ -294,8 +294,9 @@ ColumnLayout projectModel.stateListModel.appendState(item) projectModel.stateListModel.save() scenarioList.currentIndex = projectModel.stateListModel.count - 1 + clientModel.setupScenario(item); } - text: qsTr("New..") + text: qsTr("New...") roundRight: true roundLeft: false } diff --git a/mix/qml/StructView.qml b/mix/qml/StructView.qml index bc3f9499e..97c2d27b8 100644 --- a/mix/qml/StructView.qml +++ b/mix/qml/StructView.qml @@ -12,6 +12,7 @@ Column property int blockIndex property int transactionIndex property string context + property bool readOnly Layout.fillWidth: true spacing: 0 property int colHeight @@ -26,7 +27,7 @@ Column Repeater { id: repeater - visible: model.length > 0 + visible: members.length > 0 RowLayout { id: row 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 40/69] 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 41/69] 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 42/69] 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 43/69] 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 44/69] 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 45/69] 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 dac152390232dc40afde589c61e8a52bf502a36f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 12 Aug 2015 18:51:07 +0200 Subject: [PATCH 46/69] Fix transact depending on pendings. --- alethzero/Transact.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index 970c2cca0..4ccba39b9 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -346,14 +346,14 @@ GasRequirements Transact::determineGasRequirements() bool haveUpperBound = false; qint64 lowerBound = baseGas; qint64 upperBound = (qint64)ethereum()->gasLimitRemaining(); - for (unsigned i = 0; i < 20 && ((haveUpperBound && upperBound - lowerBound > 100) || !haveUpperBound); ++i) // get to with 100. + for (unsigned i = 0; i < 30 && ((haveUpperBound && upperBound - lowerBound > 16) || !haveUpperBound); ++i) // get to with 100. { qint64 mid = haveUpperBound ? (lowerBound + upperBound) / 2 : upperBound; ExecutionResult er; if (isCreation()) - er = ethereum()->create(from, value(), m_data, mid, gasPrice(), ethereum()->getDefault(), FudgeFactor::Lenient); + er = ethereum()->create(from, value(), m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient); else - er = ethereum()->call(from, value(), to, m_data, mid, gasPrice(), ethereum()->getDefault(), FudgeFactor::Lenient); + er = ethereum()->call(from, value(), to, m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient); if (er.excepted == TransactionException::OutOfGas || er.excepted == TransactionException::OutOfGasBase || er.excepted == TransactionException::OutOfGasIntrinsic || er.codeDeposit == CodeDeposit::Failed) { lowerBound = mid; From b63abaff06b670d825b7e204733dcf6fb7b0436f Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 12 Aug 2015 19:00:05 +0200 Subject: [PATCH 47/69] fixed transaction serialization --- mix/ClientModel.cpp | 2 +- mix/ContractCallDataEncoder.cpp | 14 ++++++++++++-- mix/MixClient.cpp | 33 ++++++++++++++++++++++----------- mix/qml/Block.qml | 2 ++ mix/qml/BlockChain.qml | 7 +++++++ 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 7ab6c5858..f5e978971 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -776,7 +776,7 @@ void ClientModel::onNewTransaction() case TransactionException::None: break; case TransactionException::NotEnoughCash: - emit runFailed("Insufficient balance for contract deployment"); + emit runFailed("Insufficient balance"); break; case TransactionException::OutOfGasIntrinsic: case TransactionException::OutOfGasBase: diff --git a/mix/ContractCallDataEncoder.cpp b/mix/ContractCallDataEncoder.cpp index 29bcbba8e..42cb50607 100644 --- a/mix/ContractCallDataEncoder.cpp +++ b/mix/ContractCallDataEncoder.cpp @@ -343,8 +343,18 @@ QStringList ContractCallDataEncoder::decode(QList const& if (type.array) { QJsonArray array = decodeArray(type, _v, readPosition); - QJsonDocument jsonDoc = QJsonDocument::fromVariant(array.toVariantList()); - r.append(jsonDoc.toJson(QJsonDocument::Compact)); + if (type.type == SolidityType::String && array.count() <= 1) + { + if (array.count() == 1) + r.append(array[0].toString()); + else + r.append(QString()); + } + else + { + QJsonDocument jsonDoc = QJsonDocument::fromVariant(array.toVariantList()); + r.append(jsonDoc.toJson(QJsonDocument::Compact)); + } } else { diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 2698f259e..2d43ddc96 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -130,8 +130,27 @@ ExecutionResult MixClient::debugTransaction(Transaction const& _t, State const& eth::ExecutionResult er; Executive execution(execState, _envInfo); execution.setResultRecipient(er); - execution.initialize(_t); - execution.execute(); + + ExecutionResult d; + d.address = _t.receiveAddress(); + d.sender = _t.sender(); + d.value = _t.value(); + d.inputParameters = _t.data(); + d.executonIndex = m_executions.size(); + if (!_call) + d.transactionIndex = m_postMine.pending().size(); + + try + { + execution.initialize(_t); + execution.execute(); + } + catch (Exception const& _e) + { + d.excepted = toTransactionException(_e); + d.transactionData.push_back(_t.data()); + return d; + } std::vector machineStates; std::vector levels; @@ -199,22 +218,14 @@ ExecutionResult MixClient::debugTransaction(Transaction const& _t, State const& execution.go(onOp); execution.finalize(); - ExecutionResult d; d.excepted = er.excepted; - d.inputParameters = _t.data(); d.result = er; d.machineStates = machineStates; d.executionCode = std::move(codes); d.transactionData = std::move(data); - d.address = _t.receiveAddress(); - d.sender = _t.sender(); - d.value = _t.value(); d.gasUsed = er.gasUsed + er.gasRefunded + c_callStipend; if (_t.isCreation()) d.contractAddress = right160(sha3(rlpList(_t.sender(), _t.nonce()))); - if (!_call) - d.transactionIndex = m_postMine.pending().size(); - d.executonIndex = m_executions.size(); return d; } @@ -228,7 +239,7 @@ void MixClient::executeTransaction(Transaction const& _t, Block& _block, bool _c ExecutionResult d = debugTransaction(t, _block.state(), envInfo, _call); // execute on a state - if (!_call) + if (!_call && d.excepted == TransactionException::None) { u256 useGas = min(d.gasUsed, _block.gasLimitRemaining()); t = _gasAuto ? replaceGas(_t, useGas, _secret) : _t; diff --git a/mix/qml/Block.qml b/mix/qml/Block.qml index be540919a..e64c9a525 100644 --- a/mix/qml/Block.qml +++ b/mix/qml/Block.qml @@ -12,6 +12,7 @@ ColumnLayout { id: root property variant transactions + property variant transactionModel property string status property int number property int blockWidth: Layout.preferredWidth - statusWidth - horizontalMargin @@ -202,6 +203,7 @@ ColumnLayout if (index >= 0) transactions.get(index).saveStatus = saveStatus + transactionModel[index].saveStatus = saveStatus } MouseArea { diff --git a/mix/qml/BlockChain.qml b/mix/qml/BlockChain.qml index e13b871dd..26a128e90 100644 --- a/mix/qml/BlockChain.qml +++ b/mix/qml/BlockChain.qml @@ -214,6 +214,13 @@ ColumnLayout { else return [] } + transactionModel: + { + if (index >= 0) + return scenario.blocks[index].transactions + else + return [] + } status: { From 58545a458996418c178ca243bd6e9ed79f71bc61 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 12 Aug 2015 21:19:04 +0200 Subject: [PATCH 48/69] 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 49/69] 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 50/69] 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 51/69] 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 52/69] 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 53/69] 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 54/69] 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 55/69] 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 b3f8338d56c1fcde218140f413797d87e46ae456 Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 13 Aug 2015 15:40:42 +0200 Subject: [PATCH 56/69] NewAccount ui --- alethzero/CMakeLists.txt | 15 ++- alethzero/NewAccount.cpp | 78 +++++++++++++ alethzero/NewAccount.h | 44 +++++++ alethzero/NewAccount.ui | 245 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 381 insertions(+), 1 deletion(-) create mode 100644 alethzero/NewAccount.cpp create mode 100644 alethzero/NewAccount.h create mode 100644 alethzero/NewAccount.ui diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 29bfed259..73061b38a 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -42,6 +42,7 @@ 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) +qt5_wrap_ui(ui_NewAccount.h NewAccount.ui) file(GLOB HEADERS "*.h") @@ -54,7 +55,19 @@ 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 alethzero.icns + Main.ui + Connect.ui + Debugger.ui + Transact.ui + ExportState.ui + GetPassword.ui + GasPricing.ui + AllAccounts.ui + LogPanel.ui + BrainWallet.ui + OtherAccounts.ui + NewAccount.ui WIN_RESOURCES alethzero.rc ) diff --git a/alethzero/NewAccount.cpp b/alethzero/NewAccount.cpp new file mode 100644 index 000000000..dfa808e19 --- /dev/null +++ b/alethzero/NewAccount.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 NewAccount.h + * @author Gav Wood + * @date 2015 + */ + +#include "NewAccount.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "ui_NewAccount.h" +using namespace std; +using namespace dev; +using namespace az; +using namespace eth; + +DEV_AZ_NOTE_PLUGIN(NewAccount); + +NewAccount::NewAccount(MainFace* _m): + Plugin(_m, "NewAccount") +{ + connect(addMenuItem("New Account...", "menuTools", true), SIGNAL(triggered()), SLOT(create())); +} + +NewAccount::~NewAccount() +{ +} + +void NewAccount::create() +{ + QDialog d; + Ui_NewAccount u; + u.setupUi(&d); + d.setWindowTitle("New Account Wallet"); + u.enterHexText->setEnabled(false); + u.enterPasswordText->setEnabled(false); + u.enterPasswordAgainText->setEnabled(false); + enum { NoVanity = 0, DirectICAP, FirstTwo, FirstTwoNextTwo, FirstThree, FirstFour, StringMatch }; + + QStringList items = {"No vanity (instant)", "Direct ICAP address", "Two pairs first (a few seconds)", "Two pairs first and second (a few minutes)", "Three pairs first (a few minutes)", "Four pairs first (several hours)", "Specific hex string"}; + u.selectTypeComboBox->addItems(items); + + void (QComboBox:: *indexChangedSignal)(int) = &QComboBox::currentIndexChanged; + connect(u.selectTypeComboBox, indexChangedSignal, [&](int index) { + u.enterHexText->setEnabled(index == StringMatch); + }); + + connect(u.additionalCheckBox, &QCheckBox::clicked, [&]() { + bool checked = u.additionalCheckBox->checkState() == Qt::CheckState::Checked; + u.enterPasswordText->setEnabled(checked); + u.enterPasswordAgainText->setEnabled(checked); + }); + + if (d.exec() == QDialog::Accepted) + { + //main()->noteKeysChanged(); + } +} diff --git a/alethzero/NewAccount.h b/alethzero/NewAccount.h new file mode 100644 index 000000000..d1ba1b747 --- /dev/null +++ b/alethzero/NewAccount.h @@ -0,0 +1,44 @@ +/* + 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 NewAccount.h + * @author Gav Wood + * @date 2015 + */ + +#pragma once + +#include "MainFace.h" + +namespace dev +{ +namespace az +{ + +class NewAccount: public QObject, public Plugin +{ + Q_OBJECT + +public: + NewAccount(MainFace* _m); + ~NewAccount(); + +private slots: + void create(); +}; + +} +} diff --git a/alethzero/NewAccount.ui b/alethzero/NewAccount.ui new file mode 100644 index 000000000..48d463fd5 --- /dev/null +++ b/alethzero/NewAccount.ui @@ -0,0 +1,245 @@ + + + NewAccount + + + + 0 + 0 + 511 + 600 + + + + Dialog + + + + + + + 16777215 + 50 + + + + <html><head/><body><p><span style=" font-weight:600;">Select new account type:</span></p></body></html> + + + true + + + + + + + + 16777215 + 16777215 + + + + + + + + + 16777215 + 50 + + + + <html><head/><body><p>Enter some hex digits it should begin with.<br/>NOTE: The more you enter, the longer generation will take.</p></body></html> + + + + + + + + 16777215 + 20 + + + + + + + + + 16777215 + 50 + + + + <html><head/><body><p><span style=" font-weight:600;">Enter this account name:</span></p></body></html> + + + + + + + + 16777215 + 20 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'.Helvetica Neue DeskInterface'; font-size:13pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> + + + + + + + + 16777215 + 100 + + + + <html><head/><body><p><span style=" font-weight:600;">Would you like to add additional security for this key? This lets you protect it with a different password to other keys, but also means that you need to re-enter the key's password every time you wish to use the account.</span></p></body></html> + + + true + + + + + + + Yes + + + false + + + + + + + + 16777215 + 50 + + + + <html><head/><body><p><span style=" font-weight:600;">Enter password:</span></p></body></html> + + + + + + + true + + + + 16777215 + 20 + + + + + + + + + 16777215 + 50 + + + + <html><head/><body><p><span style=" font-weight:600;">Enter password again:</span></p></body></html> + + + + + + + true + + + + 16777215 + 20 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Cancel + + + + + + + &Create + + + true + + + + + + + + + + + create + clicked() + NewAccount + accept() + + + 462 + 484 + + + 449 + 504 + + + + + cancel + clicked() + NewAccount + reject() + + + 381 + 483 + + + 351 + 506 + + + + + From 4f0b7bfbaa95fb2fba88e74ccb5233a79f8b4a13 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 13 Aug 2015 15:51:32 +0200 Subject: [PATCH 57/69] 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 58/69] 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 59/69] 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 60/69] 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) From f36a002db2f3c63364315bea0ef9e73d3b23dfb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 13 Aug 2015 18:18:56 +0200 Subject: [PATCH 61/69] Anable stack offloading for all OSs. Adjust offloading point. --- libethereum/ExtVM.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/libethereum/ExtVM.cpp b/libethereum/ExtVM.cpp index 0606745b1..33b98df98 100644 --- a/libethereum/ExtVM.cpp +++ b/libethereum/ExtVM.cpp @@ -35,13 +35,20 @@ static unsigned const c_depthLimit = 1024; /// Upper bound of stack space needed by single CALL/CREATE execution. Set experimentally. static size_t const c_singleExecutionStackSize = #ifdef NDEBUG - 12 * 1024; + 10 * 1024; #else - 33 * 1024; + 16 * 1024; #endif -/// Standard OSX thread stack limit. Should be reasonable for other platforms too. -static size_t const c_defaultStackSize = 512 * 1024; +/// Standard thread stack size. +static size_t const c_defaultStackSize = +#if defined(__linux) + 8 * 1024 * 1024; +#elif defined(_WIN32) + 16 * 1024 * 1024; +#else + 512 * 1024; // OSX and other OSs +#endif /// Stack overhead prior to allocation. static size_t const c_entryOverhead = 128 * 1024; @@ -80,7 +87,10 @@ void go(unsigned _depth, Executive& _e, OnOpFunc const& _onOp) // the rest of the calls up to the depth limit (c_depthLimit). if (_depth == c_offloadPoint) + { + cnote << "Stack offloading (depth: " << c_offloadPoint << ")"; goOnOffloadedStack(_e, _onOp); + } else _e.go(_onOp); } @@ -91,11 +101,7 @@ bool ExtVM::call(CallParameters& _p) Executive e(m_s, envInfo(), depth + 1); if (!e.call(_p, gasPrice, origin)) { -#if __clang__ // Enabled for clang only as the problem affects OSX go(depth, e, _p.onOp); -#else - e.go(_p.onOp); -#endif e.accrueSubState(sub); } _p.gas = e.gas(); From 9e40a05be124d8f09cba96af1cbb39a5460f0d37 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 13 Aug 2015 18:33:21 +0200 Subject: [PATCH 62/69] First dubby impl. --- alethzero/Transact.cpp | 160 +++++++++++++-------- alethzero/Transact.h | 11 +- alethzero/Transact.ui | 305 +++++++++++++++++++++++------------------ 3 files changed, 284 insertions(+), 192 deletions(-) diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index 4ccba39b9..f4b331d22 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -64,6 +64,8 @@ Transact::Transact(MainFace* _c, QWidget* _parent): setValueUnits(ui->valueUnits, ui->value, 0); on_destination_currentTextChanged(QString()); + + startTimer(100); } Transact::~Transact() @@ -334,6 +336,96 @@ pair Transact::toAccount() return p; } +void Transact::timerEvent(QTimerEvent*) +{ + Address from = fromAccount(); + Address to = toAccount().first; + + if (m_upperBound != m_lowerBound) + { + qint64 mid = (m_lowerBound + m_upperBound) / 2; + ExecutionResult er; + if (isCreation()) + er = ethereum()->create(from, value(), m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient); + else + er = ethereum()->call(from, value(), to, m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient); + if (er.excepted == TransactionException::OutOfGas || er.excepted == TransactionException::OutOfGasBase || er.excepted == TransactionException::OutOfGasIntrinsic || er.codeDeposit == CodeDeposit::Failed) + m_lowerBound = mid; + else + { + m_lastGood = er; + m_upperBound = mid; + } + + updateBounds(); + if (m_lowerBound == m_upperBound) + finaliseBounds(); + } +} + +void Transact::updateBounds() +{ + ui->minGas->setValue(m_lowerBound); + ui->maxGas->setValue(m_upperBound); + double oran = m_startUpperBound - m_startLowerBound; + double nran = m_upperBound - m_lowerBound; + int x = int(log2(oran / nran) * 100.0 / log2(oran * 2)); + ui->progressGas->setValue(x); +} + +void Transact::finaliseBounds() +{ + qint64 baseGas = (qint64)Transaction::gasRequired(m_data, 0); + GasRequirements gasReq = GasRequirements{m_upperBound, baseGas, m_upperBound - baseGas, (qint64)m_lastGood.gasRefunded, m_lastGood}; + + QString htmlInfo = QString("
INFO Gas required: %1 total = %2 base, %3 exec [%4 refunded later]
").arg(gasReq.neededGas).arg(gasReq.baseGas).arg(gasReq.executionGas).arg(gasReq.refundedGas); + + auto bail = [&](QString he) { + m_allGood = false; +// ui->send->setEnabled(false); + ui->code->setHtml(he + htmlInfo + ui->code->toHtml()); + }; + + auto s = fromAccount(); + auto b = ethereum()->balanceAt(s, PendingBlock); + + if (b < value() + gasReq.baseGas * gasPrice()) + { + // Not enough - bail. + bail("
ERROR Account doesn't contain enough for paying even the basic amount of gas required.
"); + return; + } + if (gasReq.neededGas > m_ethereum->gasLimitRemaining()) + { + // Not enough - bail. + bail("
ERROR Gas remaining in block isn't enough to allow the gas required.
"); + return; + } + if (gasReq.er.excepted != TransactionException::None) + { + bail("
ERROR " + QString::fromStdString(toString(gasReq.er.excepted)) + "
"); + return; + } + if (gasReq.er.codeDeposit == CodeDeposit::Failed) + { + bail("
ERROR Code deposit failed due to insufficient gas; " + QString::fromStdString(toString(gasReq.er.gasForDeposit)) + " GAS < " + QString::fromStdString(toString(gasReq.er.depositSize)) + " bytes * " + QString::fromStdString(toString(c_createDataGas)) + "GAS/byte
"); + return; + } + + // Update gas + if (ui->gas->value() == ui->gas->minimum()) + { + ui->gas->setMinimum(gasReq.neededGas); + ui->gas->setValue(gasReq.neededGas); + } + else + ui->gas->setMinimum(gasReq.neededGas); + + updateFee(); + ui->code->setHtml(htmlInfo + ui->code->toHtml()); + killTimer(m_gasCalcTimer); +} + GasRequirements Transact::determineGasRequirements() { // Determine the minimum amount of gas we need to play... @@ -343,12 +435,11 @@ GasRequirements Transact::determineGasRequirements() Address to = toAccount().first; ExecutionResult lastGood; - bool haveUpperBound = false; - qint64 lowerBound = baseGas; - qint64 upperBound = (qint64)ethereum()->gasLimitRemaining(); - for (unsigned i = 0; i < 30 && ((haveUpperBound && upperBound - lowerBound > 16) || !haveUpperBound); ++i) // get to with 100. + m_startLowerBound = baseGas; + m_startUpperBound = (qint64)ethereum()->gasLimitRemaining(); + for (unsigned i = 0; i < 30; ++i) { - qint64 mid = haveUpperBound ? (lowerBound + upperBound) / 2 : upperBound; + qint64 mid = m_startUpperBound; ExecutionResult er; if (isCreation()) er = ethereum()->create(from, value(), m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient); @@ -356,23 +447,19 @@ GasRequirements Transact::determineGasRequirements() er = ethereum()->call(from, value(), to, m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient); if (er.excepted == TransactionException::OutOfGas || er.excepted == TransactionException::OutOfGasBase || er.excepted == TransactionException::OutOfGasIntrinsic || er.codeDeposit == CodeDeposit::Failed) { - lowerBound = mid; - if (!haveUpperBound) - upperBound *= 2; + m_startLowerBound = mid; + m_startUpperBound *= 2; } else { - lastGood = er; - if (haveUpperBound) - upperBound = mid; - else - haveUpperBound = true; + m_lastGood = lastGood; + m_lowerBound = m_startLowerBound; + m_upperBound = m_startUpperBound; + startTimer(0); + return GasRequirements{m_upperBound, baseGas, m_upperBound - baseGas, (qint64)lastGood.gasRefunded, lastGood}; } } - - // Dry-run execution to determine gas requirement and any execution errors -// (qint64)(er.gasUsed + er.gasRefunded + c_callStipend); - return GasRequirements{upperBound, baseGas, upperBound - baseGas, (qint64)lastGood.gasRefunded, lastGood}; + return GasRequirements(); } void Transact::rejigData() @@ -386,8 +473,6 @@ void Transact::rejigData() if (!s) return; - auto b = ethereum()->balanceAt(s, PendingBlock); - m_allGood = true; QString htmlInfo; @@ -422,46 +507,11 @@ void Transact::rejigData() htmlInfo += "

Hex

" + QString(ETH_HTML_DIV(ETH_HTML_MONO)) + QString::fromStdString(toHex(m_data)) + ""; - auto gasReq = determineGasRequirements(); - htmlInfo = QString("
INFO Gas required: %1 total = %2 base, %3 exec [%4 refunded later]
").arg(gasReq.neededGas).arg(gasReq.baseGas).arg(gasReq.executionGas).arg(gasReq.refundedGas) + htmlInfo; - - if (b < value() + gasReq.baseGas * gasPrice()) - { - // Not enough - bail. - bail("
ERROR Account doesn't contain enough for paying even the basic amount of gas required.
"); - return; - } - if (gasReq.neededGas > m_ethereum->gasLimitRemaining()) - { - // Not enough - bail. - bail("
ERROR Gas remaining in block isn't enough to allow the gas required.
"); - return; - } - if (gasReq.er.excepted != TransactionException::None) - { - bail("
ERROR " + QString::fromStdString(toString(gasReq.er.excepted)) + "
"); - return; - } - if (gasReq.er.codeDeposit == CodeDeposit::Failed) - { - bail("
ERROR Code deposit failed due to insufficient gas; " + QString::fromStdString(toString(gasReq.er.gasForDeposit)) + " GAS < " + QString::fromStdString(toString(gasReq.er.depositSize)) + " bytes * " + QString::fromStdString(toString(c_createDataGas)) + "GAS/byte
"); - return; - } - // Add Natspec information if (!isCreation()) htmlInfo = "
INFO " + QString::fromStdString(natspecNotice(toAccount().first, m_data)).toHtmlEscaped() + "
" + htmlInfo; - // Update gas - if (ui->gas->value() == ui->gas->minimum()) - { - ui->gas->setMinimum(gasReq.neededGas); - ui->gas->setValue(gasReq.neededGas); - } - else - ui->gas->setMinimum(gasReq.neededGas); - - updateFee(); + determineGasRequirements(); ui->code->setHtml(htmlInfo); // ui->send->setEnabled(m_allGood); diff --git a/alethzero/Transact.h b/alethzero/Transact.h index 015e9d3cc..4056144c2 100644 --- a/alethzero/Transact.h +++ b/alethzero/Transact.h @@ -79,6 +79,8 @@ private: dev::eth::Client* ethereum() const { return m_ethereum; } void rejigData(); void updateNonce(); + void updateBounds(); + void finaliseBounds(); dev::Address fromAccount(); std::pair toAccount(); @@ -95,6 +97,8 @@ private: std::string natspecNotice(dev::Address _to, dev::bytes const& _data); dev::Secret findSecret(dev::u256 _totalReq) const; + void timerEvent(QTimerEvent*) override; + Ui::Transact* ui = nullptr; unsigned m_backupGas = 0; @@ -106,7 +110,12 @@ private: NatSpecFace* m_natSpecDB = nullptr; bool m_allGood = false; - bool m_determiningGas = false; + qint64 m_startLowerBound = 0; + qint64 m_startUpperBound = 0; + qint64 m_lowerBound = 0; + qint64 m_upperBound = 0; + eth::ExecutionResult m_lastGood; + int m_gasCalcTimer = 0; }; } diff --git a/alethzero/Transact.ui b/alethzero/Transact.ui index bd19808fd..3c78e3db7 100644 --- a/alethzero/Transact.ui +++ b/alethzero/Transact.ui @@ -14,6 +14,13 @@ Transact
+ + + + &Debug + + + @@ -30,71 +37,149 @@ - - + + + + + + + + + + false + + + true + + + + + + + + - &Cancel + &Optimise - - Esc + + true - - + + - &Debug + &Execute + + + false - - - - - 0 - 0 - + + + + false + + + + + + + Qt::Vertical + + + QFrame::NoFrame + + + 0 + + + + + Qt::ClickFocus + + + QFrame::NoFrame + + + 0 + + + true + + + + + + + + + + + 430000000 + + + 0 + + + + + - &To + Copy &Unsigned + + + + + + + + + + &Gas - destination + gas - - - - - + + - + 0 0 - + &To + + + destination - - + + - &Amount + &Cancel - - value + + Esc - - + + - &Execute + Auto Nonce - + + true + + false @@ -111,20 +196,30 @@ - - - - @ + + + + + 0 + 0 + - - 0 + + - - 430000000 + + + + + + &Amount + + + value - + @@ -143,74 +238,6 @@ - - - - - - - - - - 430000000 - - - 0 - - - - - - - false - - - true - - - - - - - - - - Qt::Vertical - - - - QFrame::NoFrame - - - 0 - - - - - Qt::ClickFocus - - - QFrame::NoFrame - - - 0 - - - true - - - - - - - - &Gas - - - gas - - - @@ -221,43 +248,49 @@ - - - - - - - &Optimise + + + + @ - - true + + 0 + + + 430000000 - - - - false + + + + true + + + gas + + + min - - - - Auto Nonce + + + + 24 - - true - - - false + + Calculating gas... - - - - Copy &Unsigned + + + + gas + + + max From 4c81c34d6869719aa1963c73a71ea3432aa0290a Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 13 Aug 2015 17:43:47 +0200 Subject: [PATCH 63/69] fixed another case of misplaced invariant check --- libethereum/BlockChainSync.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index 1f0e2a535..d51c25048 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -799,7 +799,6 @@ void PV60Sync::onPeerNewHashes(std::shared_ptr _peer, h256s const& void PV60Sync::abortSync() { - DEV_INVARIANT_CHECK; // Can't check invariants here since the peers is already removed from the list and the state is not updated yet. bool continueSync = false; if (m_state == SyncState::Blocks) From 6d29d724e42581ae71d5565383fb20d329e1ddab Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 13 Aug 2015 18:50:43 +0200 Subject: [PATCH 64/69] immediate invariants check --- libdevcore/Common.cpp | 8 ++++---- libdevcore/Common.h | 11 ++++++----- libethereum/BlockChainSync.cpp | 16 +++++++++------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/libdevcore/Common.cpp b/libdevcore/Common.cpp index 6fd97a781..e38d0136d 100644 --- a/libdevcore/Common.cpp +++ b/libdevcore/Common.cpp @@ -33,12 +33,12 @@ char const* Version = ETH_PROJECT_VERSION; const u256 UndefinedU256 = ~(u256)0; -void InvariantChecker::checkInvariants() const +void InvariantChecker::checkInvariants(HasInvariants const* _this, char const* _fn, char const* _file, int _line, bool _pre) { - if (!m_this->invariants()) + if (!_this->invariants()) { - cwarn << "Invariant failed in" << m_function << "at" << m_file << ":" << m_line; - ::boost::exception_detail::throw_exception_(FailedInvariant(), m_function, m_file, m_line); + cwarn << (_pre ? "Pre" : "Post") << "invariant failed in" << _fn << "at" << _file << ":" << _line; + ::boost::exception_detail::throw_exception_(FailedInvariant(), _fn, _file, _line); } } diff --git a/libdevcore/Common.h b/libdevcore/Common.h index ce637a2a6..158cea255 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -216,13 +216,12 @@ public: class InvariantChecker { public: - InvariantChecker(HasInvariants* _this, char const* _fn, char const* _file, int _line): m_this(_this), m_function(_fn), m_file(_file), m_line(_line) { checkInvariants(); } - ~InvariantChecker() { checkInvariants(); } - -private: + InvariantChecker(HasInvariants* _this, char const* _fn, char const* _file, int _line): m_this(_this), m_function(_fn), m_file(_file), m_line(_line) { checkInvariants(_this, _fn , _file, _line, true); } + ~InvariantChecker() { checkInvariants(m_this, m_function, m_file, m_line, false); } /// Check invariants are met, throw if not. - void checkInvariants() const; + static void checkInvariants(HasInvariants const* _this, char const* _fn, char const* _file, int line, bool _pre); +private: HasInvariants const* m_this; char const* m_function; char const* m_file; @@ -232,8 +231,10 @@ private: /// Scope guard for invariant check in a class derived from HasInvariants. #if ETH_DEBUG #define DEV_INVARIANT_CHECK ::dev::InvariantChecker __dev_invariantCheck(this, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__) +#define DEV_INVARIANT_CHECK_HERE ::dev::InvariantChecker::checkInvariants(this, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, true) #else #define DEV_INVARIANT_CHECK (void)0; +#define DEV_INVARIANT_CHECK_HERE (void)0; #endif /// Simple scope-based timer helper. diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp index d51c25048..7692cb91c 100644 --- a/libethereum/BlockChainSync.cpp +++ b/libethereum/BlockChainSync.cpp @@ -260,13 +260,13 @@ void BlockChainSync::onPeerBlocks(std::shared_ptr _peer, RLP const else requestBlocks(_peer); // Some of the blocks might have been downloaded by helping peers, proceed anyway } - DEV_INVARIANT_CHECK; + DEV_INVARIANT_CHECK_HERE; } void BlockChainSync::onPeerNewBlock(std::shared_ptr _peer, RLP const& _r) { - DEV_INVARIANT_CHECK; RecursiveGuard l(x_sync); + DEV_INVARIANT_CHECK; auto h = BlockInfo::headerHashFromBlock(_r[0].data()); if (_r.itemCount() != 2) @@ -441,7 +441,7 @@ void PV60Sync::transition(std::shared_ptr _peer, SyncState _s, boo // Looks like it's the best yet for total difficulty. Set to download. setState(_peer, SyncState::Blocks, isSyncing(_peer), _needHelp); // will kick off other peers to help if available. requestBlocks(_peer); - DEV_INVARIANT_CHECK; + DEV_INVARIANT_CHECK_HERE; return; } } @@ -453,7 +453,7 @@ void PV60Sync::transition(std::shared_ptr _peer, SyncState _s, boo { setState(_peer, SyncState::NewBlocks, true, _needHelp); requestBlocks(_peer); - DEV_INVARIANT_CHECK; + DEV_INVARIANT_CHECK_HERE; return; } } @@ -487,7 +487,7 @@ void PV60Sync::transition(std::shared_ptr _peer, SyncState _s, boo setState(_peer, SyncState::Idle, false); } // Otherwise it's fine. We don't care if it's Nothing->Nothing. - DEV_INVARIANT_CHECK; + DEV_INVARIANT_CHECK_HERE; return; } @@ -827,6 +827,7 @@ void PV60Sync::abortSync() // Just set to idle. Hashchain is keept, Sync will be continued if there are more peers to sync with setState(std::shared_ptr(), SyncState::Idle, false, true); } + DEV_INVARIANT_CHECK_HERE; } void PV60Sync::onPeerAborting() @@ -839,6 +840,7 @@ void PV60Sync::onPeerAborting() m_syncer.reset(); abortSync(); } + DEV_INVARIANT_CHECK_HERE; } bool PV60Sync::invariants() const @@ -1131,7 +1133,7 @@ void PV61Sync::onPeerHashes(std::shared_ptr _peer, h256s const& _h } requestSubchain(_peer); } - DEV_INVARIANT_CHECK; + DEV_INVARIANT_CHECK_HERE; } void PV61Sync::onPeerAborting() @@ -1173,7 +1175,7 @@ void PV61Sync::onPeerAborting() } else if (isPV61Syncing() && m_state == SyncState::Hashes) requestSubchains(); - DEV_INVARIANT_CHECK; + DEV_INVARIANT_CHECK_HERE; } SyncStatus PV61Sync::status() const From cb2a5ec268f5d009f9ad51c931bb1fcfe39495ac Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 13 Aug 2015 23:31:25 +0200 Subject: [PATCH 65/69] new account plugin finished --- alethzero/Main.ui | 3 +- alethzero/MainWin.cpp | 77 ------------------------ alethzero/MainWin.h | 1 - alethzero/NewAccount.cpp | 125 +++++++++++++++++++++++++++++++++------ alethzero/NewAccount.h | 14 ++++- alethzero/NewAccount.ui | 99 ++++++++++++++++++------------- 6 files changed, 179 insertions(+), 140 deletions(-) diff --git a/alethzero/Main.ui b/alethzero/Main.ui index b059b4e07..69846f34c 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -132,7 +132,7 @@ 0 0 1617 - 24 + 22 @@ -162,7 +162,6 @@ - diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index a78949413..60455969a 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -2104,83 +2104,6 @@ void Main::keysChanged() onBalancesChange(); } -bool beginsWith(Address _a, bytes const& _b) -{ - for (unsigned i = 0; i < min(20, _b.size()); ++i) - if (_a[i] != _b[i]) - return false; - return true; -} - -void Main::on_newAccount_triggered() -{ - bool ok = true; - enum { NoVanity = 0, DirectICAP, FirstTwo, FirstTwoNextTwo, FirstThree, FirstFour, StringMatch }; - QStringList items = {"No vanity (instant)", "Direct ICAP address", "Two pairs first (a few seconds)", "Two pairs first and second (a few minutes)", "Three pairs first (a few minutes)", "Four pairs first (several hours)", "Specific hex string"}; - unsigned v = items.QList::indexOf(QInputDialog::getItem(this, "Vanity Key?", "Would you a vanity key? This could take several hours.", items, 1, false, &ok)); - if (!ok) - return; - - bytes bs; - if (v == StringMatch) - { - QString s = QInputDialog::getText(this, "Vanity Beginning?", "Enter some hex digits that it should begin with.\nNOTE: The more you enter, the longer generation will take.", QLineEdit::Normal, QString(), &ok); - if (!ok) - return; - bs = fromHex(s.toStdString()); - } - - KeyPair p; - bool keepGoing = true; - unsigned done = 0; - function f = [&]() { - KeyPair lp; - while (keepGoing) - { - done++; - if (done % 1000 == 0) - cnote << "Tried" << done << "keys"; - lp = KeyPair::create(); - auto a = lp.address(); - if (v == NoVanity || - (v == DirectICAP && !a[0]) || - (v == FirstTwo && a[0] == a[1]) || - (v == FirstTwoNextTwo && a[0] == a[1] && a[2] == a[3]) || - (v == FirstThree && a[0] == a[1] && a[1] == a[2]) || - (v == FirstFour && a[0] == a[1] && a[1] == a[2] && a[2] == a[3]) || - (v == StringMatch && beginsWith(lp.address(), bs)) - ) - break; - } - if (keepGoing) - p = lp; - keepGoing = false; - }; - vector ts; - for (unsigned t = 0; t < std::thread::hardware_concurrency() - 1; ++t) - ts.push_back(new std::thread(f)); - f(); - for (std::thread* t: ts) - { - t->join(); - delete t; - } - - QString s = QInputDialog::getText(this, "Create Account", "Enter this account's name"); - if (QMessageBox::question(this, "Create Account", "Would you like to use additional security for this key? This lets you protect it with a different password to other keys, but also means you must re-enter the key's password every time you wish to use the account.", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) - { - bool ok = false; - std::string hint; - std::string password = getPassword("Create Account", "Enter the password you would like to use for this key. Don't forget it!", &hint, &ok); - if (!ok) - return; - m_keyManager.import(p.secret(), s.toStdString(), password, hint); - } - else - m_keyManager.import(p.secret(), s.toStdString()); - keysChanged(); -} - void Main::on_killAccount_triggered() { if (ui->ourAccounts->currentRow() >= 0) diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index b23a33697..c110f54e8 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -152,7 +152,6 @@ private slots: void on_preview_triggered(); // Account management - void on_newAccount_triggered(); void on_killAccount_triggered(); void on_importKey_triggered(); void on_reencryptKey_triggered(); diff --git a/alethzero/NewAccount.cpp b/alethzero/NewAccount.cpp index dfa808e19..51b320c36 100644 --- a/alethzero/NewAccount.cpp +++ b/alethzero/NewAccount.cpp @@ -15,17 +15,14 @@ along with cpp-ethereum. If not, see . */ /** @file NewAccount.h - * @author Gav Wood + * @author Marek Kotewicz * @date 2015 */ #include "NewAccount.h" #include #include -#include -#include #include -#include #include #include #include "ui_NewAccount.h" @@ -34,6 +31,14 @@ using namespace dev; using namespace az; using namespace eth; +bool beginsWith(Address _a, bytes const& _b) +{ + for (unsigned i = 0; i < min(20, _b.size()); ++i) + if (_a[i] != _b[i]) + return false; + return true; +} + DEV_AZ_NOTE_PLUGIN(NewAccount); NewAccount::NewAccount(MainFace* _m): @@ -49,30 +54,116 @@ NewAccount::~NewAccount() void NewAccount::create() { QDialog d; - Ui_NewAccount u; + Ui::NewAccount u; u.setupUi(&d); d.setWindowTitle("New Account Wallet"); - u.enterHexText->setEnabled(false); - u.enterPasswordText->setEnabled(false); - u.enterPasswordAgainText->setEnabled(false); - enum { NoVanity = 0, DirectICAP, FirstTwo, FirstTwoNextTwo, FirstThree, FirstFour, StringMatch }; + u.hexText->setEnabled(false); + u.passwordText->setEnabled(false); + u.passwordAgainText->setEnabled(false); - QStringList items = {"No vanity (instant)", "Direct ICAP address", "Two pairs first (a few seconds)", "Two pairs first and second (a few minutes)", "Three pairs first (a few minutes)", "Four pairs first (several hours)", "Specific hex string"}; - u.selectTypeComboBox->addItems(items); + QStringList items = + { + "No vanity (instant)", + "Direct ICAP address", + "Two pairs first (a few seconds)", + "Two pairs first and second (a few minutes)", + "Three pairs first (a few minutes)", + "Four pairs first (several hours)", + "Specific hex string" + }; + u.typeComboBox->addItems(items); void (QComboBox:: *indexChangedSignal)(int) = &QComboBox::currentIndexChanged; - connect(u.selectTypeComboBox, indexChangedSignal, [&](int index) { - u.enterHexText->setEnabled(index == StringMatch); + connect(u.typeComboBox, indexChangedSignal, [&](int index) + { + u.hexText->setEnabled(index == StringMatch); }); - connect(u.additionalCheckBox, &QCheckBox::clicked, [&]() { + connect(u.additionalCheckBox, &QCheckBox::clicked, [&]() + { bool checked = u.additionalCheckBox->checkState() == Qt::CheckState::Checked; - u.enterPasswordText->setEnabled(checked); - u.enterPasswordAgainText->setEnabled(checked); + u.passwordText->setEnabled(checked); + u.passwordAgainText->setEnabled(checked); + }); + + connect(u.create, &QPushButton::clicked, [&]() + { + if (u.additionalCheckBox->checkState() == Qt::CheckState::Checked && !validatePassword(u)) + { + u.passwordAgainLabel->setStyleSheet("QLabel { color : red }"); + u.passwordAgainLabel->setText("Invalid! Please re-enter password correctly:"); + return; + } + + d.accept(); }); if (d.exec() == QDialog::Accepted) + onDialogAccepted(u); + +} + +bool NewAccount::validatePassword(Ui::NewAccount const& _u) +{ + return QString::compare(_u.passwordText->toPlainText(), _u.passwordAgainText->toPlainText()) == 0; +} + +void NewAccount::onDialogAccepted(Ui::NewAccount const& _u) +{ + Type v = (Type)_u.typeComboBox->currentIndex(); + bytes bs = fromHex(_u.hexText->toPlainText().toStdString()); + KeyPair p = newKeyPair(v, bs); + QString s = _u.nameText->toPlainText(); + if (_u.additionalCheckBox->checkState() == Qt::CheckState::Checked) + { + std::string hint = _u.hintText->toPlainText().toStdString(); + std::string password = _u.passwordText->toPlainText().toStdString(); + main()->keyManager().import(p.secret(), s.toStdString(), password, hint); + } + else + main()->keyManager().import(p.secret(), s.toStdString()); + + main()->noteKeysChanged(); +} + +KeyPair NewAccount::newKeyPair(Type _type, bytes const& _prefix) +{ + KeyPair p; + bool keepGoing = true; + unsigned done = 0; + function f = [&]() { + KeyPair lp; + while (keepGoing) + { + done++; + if (done % 1000 == 0) + cnote << "Tried" << done << "keys"; + lp = KeyPair::create(); + auto a = lp.address(); + if (_type == NoVanity || + (_type == DirectICAP && !a[0]) || + (_type == FirstTwo && a[0] == a[1]) || + (_type == FirstTwoNextTwo && a[0] == a[1] && a[2] == a[3]) || + (_type == FirstThree && a[0] == a[1] && a[1] == a[2]) || + (_type == FirstFour && a[0] == a[1] && a[1] == a[2] && a[2] == a[3]) || + (_type == StringMatch && beginsWith(lp.address(), _prefix)) + ) + break; + } + if (keepGoing) + p = lp; + keepGoing = false; + }; + + vector ts; + for (unsigned t = 0; t < std::thread::hardware_concurrency() - 1; ++t) + ts.push_back(new std::thread(f)); + f(); + + for (std::thread* t: ts) { - //main()->noteKeysChanged(); + t->join(); + delete t; } + return p; } diff --git a/alethzero/NewAccount.h b/alethzero/NewAccount.h index d1ba1b747..b0031e7f1 100644 --- a/alethzero/NewAccount.h +++ b/alethzero/NewAccount.h @@ -15,7 +15,7 @@ along with cpp-ethereum. If not, see . */ /** @file NewAccount.h - * @author Gav Wood + * @author Marek Kotewicz * @date 2015 */ @@ -23,6 +23,12 @@ #include "MainFace.h" + +namespace Ui +{ +class NewAccount; +} + namespace dev { namespace az @@ -38,6 +44,12 @@ public: private slots: void create(); + +private: + enum Type { NoVanity = 0, DirectICAP, FirstTwo, FirstTwoNextTwo, FirstThree, FirstFour, StringMatch }; + bool validatePassword(Ui::NewAccount const& _u); + void onDialogAccepted(Ui::NewAccount const& _u); + KeyPair newKeyPair(Type _type, bytes const& _prefix); }; } diff --git a/alethzero/NewAccount.ui b/alethzero/NewAccount.ui index 48d463fd5..d793849d8 100644 --- a/alethzero/NewAccount.ui +++ b/alethzero/NewAccount.ui @@ -13,9 +13,12 @@ Dialog + + + - + 16777215 @@ -31,7 +34,7 @@ - + 16777215 @@ -41,7 +44,7 @@ - + 16777215 @@ -54,17 +57,17 @@ - + 16777215 - 20 + 21 - + 16777215 @@ -77,20 +80,13 @@ - + 16777215 - 20 + 21 - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'.Helvetica Neue DeskInterface'; font-size:13pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - @@ -120,7 +116,7 @@ p, li { white-space: pre-wrap; } - + 16777215 @@ -133,20 +129,17 @@ p, li { white-space: pre-wrap; } - - - true - + 16777215 - 20 + 21 - + 16777215 @@ -159,14 +152,28 @@ p, li { white-space: pre-wrap; } - - - true + + + + 16777215 + 21 + + + + + + + <html><head/><body><p><span style=" font-weight:600;">Enter hint:</span></p></body></html> + + + + + 16777215 - 20 + 50 @@ -188,6 +195,15 @@ p, li { white-space: pre-wrap; } + + + 83 + 16777215 + + + + Qt::LeftToRight + Cancel @@ -195,6 +211,21 @@ p, li { white-space: pre-wrap; } + + + 0 + 0 + + + + + 83 + 16777215 + + + + Qt::LeftToRight + &Create @@ -209,22 +240,6 @@ p, li { white-space: pre-wrap; } - - create - clicked() - NewAccount - accept() - - - 462 - 484 - - - 449 - 504 - - - cancel clicked() From f30991f6cbf657c18988a5d045ce0479629de8d0 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 14 Aug 2015 08:09:14 +0200 Subject: [PATCH 66/69] make hint text field enabled only when entering password is enabled --- alethzero/plugins/namers/NewAccount.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/alethzero/plugins/namers/NewAccount.cpp b/alethzero/plugins/namers/NewAccount.cpp index 51b320c36..64a3ea185 100644 --- a/alethzero/plugins/namers/NewAccount.cpp +++ b/alethzero/plugins/namers/NewAccount.cpp @@ -60,6 +60,7 @@ void NewAccount::create() u.hexText->setEnabled(false); u.passwordText->setEnabled(false); u.passwordAgainText->setEnabled(false); + u.hintText->setEnabled(false); QStringList items = { @@ -84,6 +85,7 @@ void NewAccount::create() bool checked = u.additionalCheckBox->checkState() == Qt::CheckState::Checked; u.passwordText->setEnabled(checked); u.passwordAgainText->setEnabled(checked); + u.hintText->setEnabled(checked); }); connect(u.create, &QPushButton::clicked, [&]() From 0ff44bd15c3fb00d93b01f811abf69964f2ec89a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 14 Aug 2015 14:20:59 +0200 Subject: [PATCH 67/69] Async transact gas determination. --- alethzero/Transact.cpp | 73 +++++++++++++++++++++--------------------- alethzero/Transact.h | 3 +- alethzero/Transact.ui | 48 ++++++++++++++++++--------- 3 files changed, 71 insertions(+), 53 deletions(-) diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index f4b331d22..ba767a6e7 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -106,7 +106,12 @@ bool Transact::isCreation() const u256 Transact::fee() const { - return ui->gas->value() * gasPrice(); + return gas() * gasPrice(); +} + +u256 Transact::gas() const +{ + return ui->gas->value() == -1 ? m_upperBound : ui->gas->value(); } u256 Transact::value() const @@ -199,10 +204,10 @@ void Transact::on_copyUnsigned_clicked() if (isCreation()) // If execution is a contract creation, add Natspec to // a local Natspec LEVELDB - t = Transaction(value(), gasPrice(), ui->gas->value(), m_data, nonce); + t = Transaction(value(), gasPrice(), gas(), m_data, nonce); else // TODO: cache like m_data. - t = Transaction(value(), gasPrice(), ui->gas->value(), toAccount().first, m_data, nonce); + t = Transaction(value(), gasPrice(), gas(), toAccount().first, m_data, nonce); qApp->clipboard()->setText(QString::fromStdString(toHex(t.rlp()))); } @@ -350,11 +355,11 @@ void Transact::timerEvent(QTimerEvent*) else er = ethereum()->call(from, value(), to, m_data, mid, gasPrice(), PendingBlock, FudgeFactor::Lenient); if (er.excepted == TransactionException::OutOfGas || er.excepted == TransactionException::OutOfGasBase || er.excepted == TransactionException::OutOfGasIntrinsic || er.codeDeposit == CodeDeposit::Failed) - m_lowerBound = mid; + m_lowerBound = m_lowerBound == mid ? m_upperBound : mid; else { m_lastGood = er; - m_upperBound = mid; + m_upperBound = m_upperBound == mid ? m_lowerBound : mid; } updateBounds(); @@ -371,58 +376,52 @@ void Transact::updateBounds() double nran = m_upperBound - m_lowerBound; int x = int(log2(oran / nran) * 100.0 / log2(oran * 2)); ui->progressGas->setValue(x); + ui->progressGas->setVisible(true); + ui->gas->setSpecialValueText(QString("Auto (%1 gas)").arg(m_upperBound)); } void Transact::finaliseBounds() { - qint64 baseGas = (qint64)Transaction::gasRequired(m_data, 0); - GasRequirements gasReq = GasRequirements{m_upperBound, baseGas, m_upperBound - baseGas, (qint64)m_lastGood.gasRefunded, m_lastGood}; + quint64 baseGas = (quint64)Transaction::gasRequired(m_data, 0); + ui->progressGas->setVisible(false); - QString htmlInfo = QString("
INFO Gas required: %1 total = %2 base, %3 exec [%4 refunded later]
").arg(gasReq.neededGas).arg(gasReq.baseGas).arg(gasReq.executionGas).arg(gasReq.refundedGas); + quint64 executionGas = m_upperBound - baseGas; + QString htmlInfo = QString("
INFO Gas required: %1 total = %2 base, %3 exec [%4 refunded later]
").arg(m_upperBound).arg(baseGas).arg(executionGas).arg((qint64)m_lastGood.gasRefunded); auto bail = [&](QString he) { - m_allGood = false; -// ui->send->setEnabled(false); - ui->code->setHtml(he + htmlInfo + ui->code->toHtml()); + ui->send->setEnabled(false); + ui->code->setHtml(he + htmlInfo + m_dataInfo); }; auto s = fromAccount(); auto b = ethereum()->balanceAt(s, PendingBlock); - if (b < value() + gasReq.baseGas * gasPrice()) + if (b < value() + baseGas * gasPrice()) { // Not enough - bail. bail("
ERROR Account doesn't contain enough for paying even the basic amount of gas required.
"); return; } - if (gasReq.neededGas > m_ethereum->gasLimitRemaining()) + if (m_upperBound > m_ethereum->gasLimitRemaining()) { // Not enough - bail. bail("
ERROR Gas remaining in block isn't enough to allow the gas required.
"); return; } - if (gasReq.er.excepted != TransactionException::None) + if (m_lastGood.excepted != TransactionException::None) { - bail("
ERROR " + QString::fromStdString(toString(gasReq.er.excepted)) + "
"); + bail("
ERROR " + QString::fromStdString(toString(m_lastGood.excepted)) + "
"); return; } - if (gasReq.er.codeDeposit == CodeDeposit::Failed) + if (m_lastGood.codeDeposit == CodeDeposit::Failed) { - bail("
ERROR Code deposit failed due to insufficient gas; " + QString::fromStdString(toString(gasReq.er.gasForDeposit)) + " GAS < " + QString::fromStdString(toString(gasReq.er.depositSize)) + " bytes * " + QString::fromStdString(toString(c_createDataGas)) + "GAS/byte
"); + bail("
ERROR Code deposit failed due to insufficient gas; " + QString::fromStdString(toString(m_lastGood.gasForDeposit)) + " GAS < " + QString::fromStdString(toString(m_lastGood.depositSize)) + " bytes * " + QString::fromStdString(toString(c_createDataGas)) + "GAS/byte
"); return; } - // Update gas - if (ui->gas->value() == ui->gas->minimum()) - { - ui->gas->setMinimum(gasReq.neededGas); - ui->gas->setValue(gasReq.neededGas); - } - else - ui->gas->setMinimum(gasReq.neededGas); - updateFee(); - ui->code->setHtml(htmlInfo + ui->code->toHtml()); + ui->code->setHtml(htmlInfo + m_dataInfo); + ui->send->setEnabled(true); killTimer(m_gasCalcTimer); } @@ -473,13 +472,12 @@ void Transact::rejigData() if (!s) return; - m_allGood = true; QString htmlInfo; auto bail = [&](QString he) { - m_allGood = false; -// ui->send->setEnabled(false); - ui->code->setHtml(he + htmlInfo); + ui->send->setEnabled(false); + m_dataInfo = he + htmlInfo; + ui->code->setHtml(m_dataInfo); }; // Determine m_info. @@ -513,8 +511,9 @@ void Transact::rejigData() determineGasRequirements(); - ui->code->setHtml(htmlInfo); -// ui->send->setEnabled(m_allGood); + m_dataInfo = htmlInfo; + ui->code->setHtml(m_dataInfo); + ui->send->setEnabled(true); } Secret Transact::findSecret(u256 _totalReq) const @@ -576,7 +575,7 @@ void Transact::on_send_clicked() { // If execution is a contract creation, add Natspec to // a local Natspec LEVELDB - ethereum()->submitTransaction(s, value(), m_data, ui->gas->value(), gasPrice(), nonce); + ethereum()->submitTransaction(s, value(), m_data, gas(), gasPrice(), nonce); #if ETH_SOLIDITY string src = ui->data->toPlainText().toStdString(); if (sourceIsSolidity(src)) @@ -595,7 +594,7 @@ void Transact::on_send_clicked() } else // TODO: cache like m_data. - ethereum()->submitTransaction(s, value(), toAccount().first, m_data, ui->gas->value(), gasPrice(), nonce); + ethereum()->submitTransaction(s, value(), toAccount().first, m_data, gas(), gasPrice(), nonce); close(); } @@ -614,8 +613,8 @@ void Transact::on_debug_clicked() { Block postState(ethereum()->postState()); Transaction t = isCreation() ? - Transaction(value(), gasPrice(), ui->gas->value(), m_data, postState.transactionsFrom(from)) : - Transaction(value(), gasPrice(), ui->gas->value(), toAccount().first, m_data, postState.transactionsFrom(from)); + Transaction(value(), gasPrice(), gas(), m_data, postState.transactionsFrom(from)) : + Transaction(value(), gasPrice(), gas(), toAccount().first, m_data, postState.transactionsFrom(from)); t.forceSender(from); Debugger dw(m_main, this); Executive e(postState, ethereum()->blockChain(), 0); diff --git a/alethzero/Transact.h b/alethzero/Transact.h index 4056144c2..723ff07db 100644 --- a/alethzero/Transact.h +++ b/alethzero/Transact.h @@ -88,6 +88,7 @@ private: void updateFee(); bool isCreation() const; dev::u256 fee() const; + dev::u256 gas() const; dev::u256 total() const; dev::u256 value() const; dev::u256 gasPrice() const; @@ -108,8 +109,8 @@ private: dev::eth::Client* m_ethereum = nullptr; MainFace* m_main = nullptr; NatSpecFace* m_natSpecDB = nullptr; - bool m_allGood = false; + QString m_dataInfo; qint64 m_startLowerBound = 0; qint64 m_startUpperBound = 0; qint64 m_lowerBound = 0; diff --git a/alethzero/Transact.ui b/alethzero/Transact.ui index 3c78e3db7..94b329842 100644 --- a/alethzero/Transact.ui +++ b/alethzero/Transact.ui @@ -6,7 +6,7 @@ 0 0 - 543 + 604 695
@@ -23,17 +23,20 @@
+ + Automatic + gas - 1 + -1 430000000 - 10000 + -1 @@ -261,7 +264,20 @@
- + + + + gas + + + max + + + 450000000 + + + + true @@ -272,10 +288,22 @@ min + + 0 + + + 450000000 + - + + + + 0 + 0 + + 24 @@ -284,16 +312,6 @@
- - - - gas - - - max - - -
From e69a0c1819d85e3da2d837433b24da9bd0d25c0f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 14 Aug 2015 15:08:51 +0200 Subject: [PATCH 68/69] Forgot to record the timer id. --- alethzero/Transact.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index ba767a6e7..cb52eb315 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -451,10 +451,11 @@ GasRequirements Transact::determineGasRequirements() } else { + // Begin async binary chop for gas calculation.. m_lastGood = lastGood; m_lowerBound = m_startLowerBound; m_upperBound = m_startUpperBound; - startTimer(0); + m_gasCalcTimer = startTimer(0); return GasRequirements{m_upperBound, baseGas, m_upperBound - baseGas, (qint64)lastGood.gasRefunded, lastGood}; } } From 60b0dcbbe05cc0b66b99bdc734bc59610ece08ae Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 14 Aug 2015 15:20:21 +0200 Subject: [PATCH 69/69] Don't start timer, cleanup before next time. --- alethzero/Transact.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/alethzero/Transact.cpp b/alethzero/Transact.cpp index cb52eb315..c9d687ef3 100644 --- a/alethzero/Transact.cpp +++ b/alethzero/Transact.cpp @@ -64,8 +64,6 @@ Transact::Transact(MainFace* _c, QWidget* _parent): setValueUnits(ui->valueUnits, ui->value, 0); on_destination_currentTextChanged(QString()); - - startTimer(100); } Transact::~Transact() @@ -455,6 +453,7 @@ GasRequirements Transact::determineGasRequirements() m_lastGood = lastGood; m_lowerBound = m_startLowerBound; m_upperBound = m_startUpperBound; + killTimer(m_gasCalcTimer); m_gasCalcTimer = startTimer(0); return GasRequirements{m_upperBound, baseGas, m_upperBound - baseGas, (qint64)lastGood.gasRefunded, lastGood}; }