diff --git a/alethzero/CMakeLists.txt b/alethzero/CMakeLists.txt index 9e41260fe..008721518 100644 --- a/alethzero/CMakeLists.txt +++ b/alethzero/CMakeLists.txt @@ -10,8 +10,8 @@ endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) -include_directories(..) include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) +include_directories(BEFORE ..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) qt5_wrap_ui(ui_Main.h Main.ui) diff --git a/alethzero/Context.h b/alethzero/Context.h index a2fb1a130..098690455 100644 --- a/alethzero/Context.h +++ b/alethzero/Context.h @@ -29,7 +29,7 @@ class QComboBox; -namespace dev { namespace eth { class StateDiff; } } +namespace dev { namespace eth { struct StateDiff; } } #define Small "font-size: small; " #define Mono "font-family: Ubuntu Mono, Monospace, Lucida Console, Courier New; font-weight: bold; " diff --git a/eth/CMakeLists.txt b/eth/CMakeLists.txt index 31aa8df96..ed65862a4 100644 --- a/eth/CMakeLists.txt +++ b/eth/CMakeLists.txt @@ -3,9 +3,9 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) +include_directories(BEFORE ..) include_directories(${Boost_INCLUDE_DIRS}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) -include_directories(..) set(EXECUTABLE eth) diff --git a/exp/CMakeLists.txt b/exp/CMakeLists.txt index d0aadc8ae..548f48da8 100644 --- a/exp/CMakeLists.txt +++ b/exp/CMakeLists.txt @@ -3,8 +3,8 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) +include_directories(BEFORE ..) include_directories(${LEVELDB_INCLUDE_DIRS}) -include_directories(..) set(EXECUTABLE exp) diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index 40aa7ce24..e3851b7ce 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -12,8 +12,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(BEFORE ..) include_directories(${Boost_INCLUDE_DIRS}) -include_directories(..) set(EXECUTABLE devcore) diff --git a/libdevcore/RLP.cpp b/libdevcore/RLP.cpp index d72b5c20b..0dd61b876 100644 --- a/libdevcore/RLP.cpp +++ b/libdevcore/RLP.cpp @@ -177,7 +177,7 @@ void RLPStream::noteAppended(unsigned _itemCount) while (m_listStack.size()) { if (m_listStack.back().first < _itemCount) - BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("itemCount too large")); + BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("itemCount too large") << RequirementError((bigint)m_listStack.back().first, (bigint)_itemCount)); m_listStack.back().first -= _itemCount; if (m_listStack.back().first) break; diff --git a/libdevcrypto/CMakeLists.txt b/libdevcrypto/CMakeLists.txt index 4cd6daf21..e3c3a1677 100644 --- a/libdevcrypto/CMakeLists.txt +++ b/libdevcrypto/CMakeLists.txt @@ -9,10 +9,10 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) +include_directories(BEFORE ..) include_directories(${Boost_INCLUDE_DIRS}) include_directories(${CRYPTOPP_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIRS}) -include_directories(..) set(EXECUTABLE devcrypto) diff --git a/libethcore/BlockInfo.cpp b/libethcore/BlockInfo.cpp index 3d1bcaa2a..8726ebe95 100644 --- a/libethcore/BlockInfo.cpp +++ b/libethcore/BlockInfo.cpp @@ -134,7 +134,7 @@ void BlockInfo::populate(bytesConstRef _block, bool _checkNonce) RLP header = root[0]; if (!header.isList()) - BOOST_THROW_EXCEPTION(InvalidBlockFormat(0,header.data())); + BOOST_THROW_EXCEPTION(InvalidBlockFormat(0,header.data()) << errinfo_comment("block header needs to be a list")); populateFromHeader(header, _checkNonce); if (!root[1].isList()) @@ -157,8 +157,8 @@ void BlockInfo::verifyInternals(bytesConstRef _block) const { bytes k = rlp(i); t.insert(&k, tr.data()); - u256 gp = tr[1].toInt(); - mgp = min(mgp, gp); + u256 gasprice = tr[1].toInt(); + mgp = min(mgp, gasprice); // the minimum gas price is not used for anything //TODO delete? ++i; } if (transactionsRoot != t.root()) diff --git a/libethcore/CMakeLists.txt b/libethcore/CMakeLists.txt index 984aa3ce5..920f9f652 100644 --- a/libethcore/CMakeLists.txt +++ b/libethcore/CMakeLists.txt @@ -9,8 +9,8 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) +include_directories(BEFORE ..) include_directories(${Boost_INCLUDE_DIRS}) -include_directories(..) set(EXECUTABLE ethcore) diff --git a/libethcore/Exceptions.h b/libethcore/Exceptions.h index 6127a3d00..3fd62afbd 100644 --- a/libethcore/Exceptions.h +++ b/libethcore/Exceptions.h @@ -51,6 +51,7 @@ struct UncleTooOld: virtual dev::Exception {}; class UncleInChain: virtual public dev::Exception { public: UncleInChain(h256Set _uncles, h256 _block): m_uncles(_uncles), m_block(_block) {} h256Set m_uncles; h256 m_block; virtual const char* what() const noexcept; }; struct DuplicateUncleNonce: virtual dev::Exception {}; struct InvalidStateRoot: virtual dev::Exception {}; +struct InvalidGasUsed: virtual dev::Exception {}; class InvalidTransactionsHash: virtual public dev::Exception { public: InvalidTransactionsHash(h256 _head, h256 _real): m_head(_head), m_real(_real) {} h256 m_head; h256 m_real; virtual const char* what() const noexcept; }; struct InvalidTransaction: virtual dev::Exception {}; struct InvalidDifficulty: virtual dev::Exception {}; diff --git a/libethereum/CMakeLists.txt b/libethereum/CMakeLists.txt index 3906074fd..86157fdc2 100644 --- a/libethereum/CMakeLists.txt +++ b/libethereum/CMakeLists.txt @@ -11,8 +11,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(BEFORE ..) include_directories(${LEVELDB_INCLUDE_DIRS}) -include_directories(..) set(EXECUTABLE ethereum) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 4a49812df..d72762f36 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -714,6 +714,20 @@ BlockInfo Client::uncle(h256 _blockHash, unsigned _i) const return BlockInfo(); } +unsigned Client::transactionCount(h256 _blockHash) const +{ + auto bl = m_bc.block(_blockHash); + RLP b(bl); + return b[1].itemCount(); +} + +unsigned Client::uncleCount(h256 _blockHash) const +{ + auto bl = m_bc.block(_blockHash); + RLP b(bl); + return b[2].itemCount(); +} + LocalisedLogEntries Client::logs(LogFilter const& _f) const { LocalisedLogEntries ret; diff --git a/libethereum/Client.h b/libethereum/Client.h index cb4488b17..f4ab5ce76 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -229,6 +229,8 @@ public: virtual BlockDetails blockDetails(h256 _hash) const { return m_bc.details(_hash); } virtual Transaction transaction(h256 _blockHash, unsigned _i) const; virtual BlockInfo uncle(h256 _blockHash, unsigned _i) const; + virtual unsigned transactionCount(h256 _blockHash) const; + virtual unsigned uncleCount(h256 _blockHash) const; /// Differences between transactions. using Interface::diff; diff --git a/libethereum/Interface.h b/libethereum/Interface.h index 09a134f1f..847c181e0 100644 --- a/libethereum/Interface.h +++ b/libethereum/Interface.h @@ -103,6 +103,8 @@ public: virtual BlockDetails blockDetails(h256 _hash) const = 0; virtual Transaction transaction(h256 _blockHash, unsigned _i) const = 0; virtual BlockInfo uncle(h256 _blockHash, unsigned _i) const = 0; + virtual unsigned transactionCount(h256 _blockHash) const = 0; + virtual unsigned uncleCount(h256 _blockHash) const = 0; // [EXTRA API]: diff --git a/libethereum/State.cpp b/libethereum/State.cpp index beab32abb..5b9da0cdd 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -600,6 +600,13 @@ u256 State::enact(bytesConstRef _block, BlockChain const& _bc, bool _checkNonce) BOOST_THROW_EXCEPTION(InvalidStateRoot()); } + if (m_currentBlock.gasUsed != gasUsed()) + { + // Rollback the trie. + m_db.rollback(); + BOOST_THROW_EXCEPTION(InvalidGasUsed() << RequirementError(bigint(gasUsed()), bigint(m_currentBlock.gasUsed))); + } + return tdIncrease; } diff --git a/libethereum/State.h b/libethereum/State.h index 17e773a95..813141d17 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -132,7 +132,7 @@ public: * commitToMine(_blockChain); // will call uncommitToMine if a repeat. * // unlock * MineInfo info; - * for (info.complete = false; !info.complete; info = mine()) {} + * for (info.completed = false; !info.completed; info = mine()) {} * } * // lock * completeMine(); diff --git a/libethereumx/CMakeLists.txt b/libethereumx/CMakeLists.txt index 4a3cdcda7..373ff8d71 100644 --- a/libethereumx/CMakeLists.txt +++ b/libethereumx/CMakeLists.txt @@ -4,7 +4,8 @@ set(CMAKE_AUTOMOC OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) -include_directories(..) + +include_directories(BEFORE ..) set(EXECUTABLE ethereumx) diff --git a/libevm/CMakeLists.txt b/libevm/CMakeLists.txt index 4af5eb175..b04df70ea 100644 --- a/libevm/CMakeLists.txt +++ b/libevm/CMakeLists.txt @@ -13,8 +13,8 @@ aux_source_directory(. SRC_LIST) # we may not use it in libevm, but one of our dependecies is including boost in header file # and windows is failing to build without that +include_directories(BEFORE ..) include_directories(${Boost_INCLUDE_DIRS}) -include_directories(..) set(EXECUTABLE evm) diff --git a/libevmcore/CMakeLists.txt b/libevmcore/CMakeLists.txt index 9727ee1c9..0f8494804 100644 --- a/libevmcore/CMakeLists.txt +++ b/libevmcore/CMakeLists.txt @@ -11,8 +11,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(BEFORE ..) include_directories(${Boost_INCLUDE_DIRS}) -include_directories(..) set(EXECUTABLE evmcore) diff --git a/liblll/CMakeLists.txt b/liblll/CMakeLists.txt index fb79d5873..3b9dc6030 100644 --- a/liblll/CMakeLists.txt +++ b/liblll/CMakeLists.txt @@ -11,8 +11,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(BEFORE ..) include_directories(${Boost_INCLUDE_DIRS}) -include_directories(..) set(EXECUTABLE lll) diff --git a/libnatspec/CMakeLists.txt b/libnatspec/CMakeLists.txt index b5bd7903e..af15d56a9 100644 --- a/libnatspec/CMakeLists.txt +++ b/libnatspec/CMakeLists.txt @@ -13,7 +13,7 @@ set(CMAKE_AUTOMOC OFF) set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) -include_directories(..) +include_directories(BEFORE ..) set(EXECUTABLE natspec) diff --git a/libp2p/CMakeLists.txt b/libp2p/CMakeLists.txt index 6f3f6b712..83309be78 100644 --- a/libp2p/CMakeLists.txt +++ b/libp2p/CMakeLists.txt @@ -11,6 +11,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) +include_directories(BEFORE ..) # we may not use it in libp2p, but one of our dependecies is including leveldb in header file # and windows is failing to build without that include_directories(${LEVELDB_INCLUDE_DIRS}) @@ -18,7 +19,6 @@ include_directories(${LEVELDB_INCLUDE_DIRS}) if (MINIUPNPC_FOUND) include_directories(${MINIUPNPC_INCLUDE_DIRS}) endif() -include_directories(..) set(EXECUTABLE p2p) diff --git a/libserpent/CMakeLists.txt b/libserpent/CMakeLists.txt index 1c5b8e147..45dfa339d 100644 --- a/libserpent/CMakeLists.txt +++ b/libserpent/CMakeLists.txt @@ -11,7 +11,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) -include_directories(..) +include_directories(BEFORE ..) set(EXECUTABLE serpent) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 0dbad433f..c6d8f5c58 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -274,6 +274,15 @@ TypePointer FunctionDefinition::getType(ContractDefinition const*) const void FunctionDefinition::checkTypeRequirements() { + // change all byte arrays parameters to point to calldata + if (getVisibility() == Visibility::External) + for (ASTPointer const& var: getParameters()) + { + auto const& type = var->getType(); + solAssert(!!type, ""); + if (auto const* byteArrayType = dynamic_cast(type.get())) + var->setType(byteArrayType->copyForLocation(ByteArrayType::Location::CallData)); + } for (ASTPointer const& var: getParameters() + getReturnParameters()) if (!var->getType()->canLiveOutsideStorage()) BOOST_THROW_EXCEPTION(var->createTypeError("Type is required to live outside storage.")); @@ -288,12 +297,23 @@ string FunctionDefinition::getCanonicalSignature() const return FunctionType(*this).getCanonicalSignature(getName()); } -Declaration::LValueType VariableDeclaration::getLValueType() const +bool VariableDeclaration::isLValue() const { - if (dynamic_cast(getScope()) || dynamic_cast(getScope())) - return Declaration::LValueType::Local; - else - return Declaration::LValueType::Storage; + if (auto const* function = dynamic_cast(getScope())) + if (function->getVisibility() == Declaration::Visibility::External && isFunctionParameter()) + return false; + return true; +} + +bool VariableDeclaration::isFunctionParameter() const +{ + auto const* function = dynamic_cast(getScope()); + if (!function) + return false; + for (auto const& variable: function->getParameters()) + if (variable.get() == this) + return true; + return false; } TypePointer ModifierDefinition::getType(ContractDefinition const*) const @@ -586,8 +606,7 @@ void MemberAccess::checkTypeRequirements() if (!m_type) BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found or not " "visible in " + type.toString())); - //@todo later, this will not always be STORAGE - m_lvalue = type.getCategory() == Type::Category::Struct ? Declaration::LValueType::Storage : Declaration::LValueType::None; + m_isLValue = (type.getCategory() == Type::Category::Struct); } void IndexAccess::checkTypeRequirements() @@ -599,14 +618,14 @@ void IndexAccess::checkTypeRequirements() MappingType const& type = dynamic_cast(*m_base->getType()); m_index->expectType(*type.getKeyType()); m_type = type.getValueType(); - m_lvalue = Declaration::LValueType::Storage; + m_isLValue = true; } void Identifier::checkTypeRequirements() { solAssert(m_referencedDeclaration, "Identifier not resolved."); - m_lvalue = m_referencedDeclaration->getLValueType(); + m_isLValue = m_referencedDeclaration->isLValue(); m_type = m_referencedDeclaration->getType(m_currentContract); if (!m_type) BOOST_THROW_EXCEPTION(createTypeError("Declaration referenced before type could be determined.")); diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 51d8031a3..af45934f7 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -132,8 +132,8 @@ private: class Declaration: public ASTNode { public: - enum class LValueType { None, Local, Storage }; - enum class Visibility { Default, Public, Protected, Private }; + /// Visibility ordered from restricted to unrestricted. + enum class Visibility { Default, Private, Protected, Public, External }; Declaration(Location const& _location, ASTPointer const& _name, Visibility _visibility = Visibility::Default): @@ -142,7 +142,9 @@ public: /// @returns the declared name. ASTString const& getName() const { return *m_name; } Visibility getVisibility() const { return m_visibility == Visibility::Default ? getDefaultVisibility() : m_visibility; } - bool isPublic() const { return getVisibility() == Visibility::Public; } + bool isPublic() const { return getVisibility() >= Visibility::Public; } + bool isVisibleInContract() const { return getVisibility() != Visibility::External; } + bool isVisibleInDerivedContracts() const { return isVisibleInContract() && getVisibility() >= Visibility::Protected; } /// @returns the scope this declaration resides in. Can be nullptr if it is the global scope. /// Available only after name and type resolution step. @@ -153,8 +155,7 @@ public: /// The current contract has to be given since this context can change the type, especially of /// contract types. virtual TypePointer getType(ContractDefinition const* m_currentContract = nullptr) const = 0; - /// @returns the lvalue type of expressions referencing this declaration - virtual LValueType getLValueType() const { return LValueType::None; } + virtual bool isLValue() const { return false; } protected: virtual Visibility getDefaultVisibility() const { return Visibility::Public; } @@ -445,8 +446,9 @@ public: TypePointer getType(ContractDefinition const* = nullptr) const { return m_type; } void setType(std::shared_ptr const& _type) { m_type = _type; } - virtual LValueType getLValueType() const override; + virtual bool isLValue() const override; bool isLocalVariable() const { return !!dynamic_cast(getScope()); } + bool isFunctionParameter() const; bool isStateVariable() const { return m_isStateVariable; } bool isIndexed() const { return m_isIndexed; } @@ -884,8 +886,7 @@ public: virtual void checkTypeRequirements() = 0; std::shared_ptr const& getType() const { return m_type; } - bool isLValue() const { return m_lvalue != Declaration::LValueType::None; } - bool isLocalLValue() const { return m_lvalue == Declaration::LValueType::Local; } + bool isLValue() const { return m_isLValue; } /// Helper function, infer the type via @ref checkTypeRequirements and then check that it /// is implicitly convertible to @a _expectedType. If not, throw exception. @@ -900,9 +901,9 @@ public: protected: //! Inferred type of the expression, only filled after a call to checkTypeRequirements(). std::shared_ptr m_type; - //! If this expression is an lvalue (i.e. something that can be assigned to) and is stored - //! locally or in storage. This is set during calls to @a checkTypeRequirements() - Declaration::LValueType m_lvalue = Declaration::LValueType::None; + //! If this expression is an lvalue (i.e. something that can be assigned to). + //! This is set during calls to @a checkTypeRequirements() + bool m_isLValue = false; //! Whether the outer expression requested the address (true) or the value (false) of this expression. bool m_lvalueRequested = false; }; diff --git a/libsolidity/ASTJsonConverter.cpp b/libsolidity/ASTJsonConverter.cpp index a216a59ac..04feafe2f 100644 --- a/libsolidity/ASTJsonConverter.cpp +++ b/libsolidity/ASTJsonConverter.cpp @@ -118,11 +118,7 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node) bool ASTJsonConverter::visit(VariableDeclaration const& _node) { - bool isLocalVariable = (_node.getLValueType() == VariableDeclaration::LValueType::Local); - addJsonNode("VariableDeclaration", - { make_pair("name", _node.getName()), - make_pair("local", boost::lexical_cast(isLocalVariable))}, - true); + addJsonNode("VariableDeclaration", { make_pair("name", _node.getName()) }, true); return true; } @@ -216,11 +212,12 @@ bool ASTJsonConverter::visit(ExpressionStatement const&) bool ASTJsonConverter::visit(Expression const& _node) { - addJsonNode("Expression", - { make_pair("type", getType(_node)), - make_pair("lvalue", boost::lexical_cast(_node.isLValue())), - make_pair("local_lvalue", boost::lexical_cast(_node.isLocalLValue())) }, - true); + addJsonNode( + "Expression", + { make_pair("type", getType(_node)), + make_pair("lvalue", boost::lexical_cast(_node.isLValue())) }, + true + ); return true; } diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index cccc5e165..2b1059c69 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -11,8 +11,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATICLIB") aux_source_directory(. SRC_LIST) -include_directories(..) include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) +include_directories(BEFORE ..) include_directories(${Boost_INCLUDE_DIRS}) set(EXECUTABLE solidity) diff --git a/libsolidity/Compiler.cpp b/libsolidity/Compiler.cpp index dad79bb06..14acc0113 100644 --- a/libsolidity/Compiler.cpp +++ b/libsolidity/Compiler.cpp @@ -147,7 +147,7 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract) // retrieve the function signature hash from the calldata if (!interfaceFunctions.empty()) - CompilerUtils(m_context).loadFromMemory(0, 4, false, true); + CompilerUtils(m_context).loadFromMemory(0, IntegerType(CompilerUtils::dataStartOffset * 8), true); // stack now is: 1 0 for (auto const& it: interfaceFunctions) @@ -178,23 +178,46 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract) } } -unsigned Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool _fromMemory) +void Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, bool _fromMemory) { // We do not check the calldata size, everything is zero-padded. - unsigned dataOffset = CompilerUtils::dataStartOffset; // the 4 bytes of the function hash signature - //@todo this can be done more efficiently, saving some CALLDATALOAD calls + unsigned offset(CompilerUtils::dataStartOffset); + bool const c_padToWords = true; + + unsigned dynamicParameterCount = 0; for (TypePointer const& type: _typeParameters) - { - unsigned const c_numBytes = type->getCalldataEncodedSize(); - if (c_numBytes > 32) - BOOST_THROW_EXCEPTION(CompilerError() - << errinfo_comment("Type " + type->toString() + " not yet supported.")); - bool const c_leftAligned = type->getCategory() == Type::Category::String; - bool const c_padToWords = true; - dataOffset += CompilerUtils(m_context).loadFromMemory(dataOffset, c_numBytes, c_leftAligned, - !_fromMemory, c_padToWords); - } - return dataOffset; + if (type->isDynamicallySized()) + dynamicParameterCount++; + offset += dynamicParameterCount * 32; + unsigned currentDynamicParameter = 0; + for (TypePointer const& type: _typeParameters) + if (type->isDynamicallySized()) + { + // value on stack: [calldata_offset] (only if we are already in dynamic mode) + if (currentDynamicParameter == 0) + // switch from static to dynamic + m_context << u256(offset); + // retrieve length + CompilerUtils(m_context).loadFromMemory( + CompilerUtils::dataStartOffset + currentDynamicParameter * 32, + IntegerType(256), !_fromMemory, c_padToWords); + // stack: offset length + // add 32-byte padding to copy of length + m_context << u256(32) << eth::Instruction::DUP1 << u256(31) + << eth::Instruction::DUP4 << eth::Instruction::ADD + << eth::Instruction::DIV << eth::Instruction::MUL; + // stack: offset length padded_length + m_context << eth::Instruction::DUP3 << eth::Instruction::ADD; + currentDynamicParameter++; + // stack: offset length next_calldata_offset + } + else if (currentDynamicParameter == 0) + // we can still use static load + offset += CompilerUtils(m_context).loadFromMemory(offset, *type, !_fromMemory, c_padToWords); + else + CompilerUtils(m_context).loadFromMemoryDynamic(*type, !_fromMemory, c_padToWords); + if (dynamicParameterCount > 0) + m_context << eth::Instruction::POP; } void Compiler::appendReturnValuePacker(TypePointers const& _typeParameters) diff --git a/libsolidity/Compiler.h b/libsolidity/Compiler.h index b3eae5b17..1aeaee88f 100644 --- a/libsolidity/Compiler.h +++ b/libsolidity/Compiler.h @@ -20,6 +20,8 @@ * Solidity AST to EVM bytecode compiler. */ +#pragma once + #include #include #include @@ -52,8 +54,8 @@ private: void appendConstructorCall(FunctionDefinition const& _constructor); void appendFunctionSelector(ContractDefinition const& _contract); /// Creates code that unpacks the arguments for the given function represented by a vector of TypePointers. - /// From memory if @a _fromMemory is true, otherwise from call data. @returns the size of the data in bytes. - unsigned appendCalldataUnpacker(TypePointers const& _typeParameters, bool _fromMemory = false); + /// From memory if @a _fromMemory is true, otherwise from call data. + void appendCalldataUnpacker(TypePointers const& _typeParameters, bool _fromMemory = false); void appendReturnValuePacker(TypePointers const& _typeParameters); void registerStateVariables(ContractDefinition const& _contract); diff --git a/libsolidity/CompilerUtils.cpp b/libsolidity/CompilerUtils.cpp index dda1736d6..047bc6d62 100644 --- a/libsolidity/CompilerUtils.cpp +++ b/libsolidity/CompilerUtils.cpp @@ -33,35 +33,26 @@ namespace solidity const unsigned int CompilerUtils::dataStartOffset = 4; -unsigned CompilerUtils::loadFromMemory(unsigned _offset, unsigned _bytes, bool _leftAligned, - bool _fromCalldata, bool _padToWordBoundaries) +unsigned CompilerUtils::loadFromMemory(unsigned _offset, Type const& _type, + bool _fromCalldata, bool _padToWordBoundaries) { - if (_bytes == 0) - { - m_context << u256(0); - return 0; - } - eth::Instruction load = _fromCalldata ? eth::Instruction::CALLDATALOAD : eth::Instruction::MLOAD; - solAssert(_bytes <= 32, "Memory load of more than 32 bytes requested."); - if (_bytes == 32 || _padToWordBoundaries) - { - m_context << u256(_offset) << load; - return 32; - } - else - { - // load data and add leading or trailing zeros by dividing/multiplying depending on alignment - u256 shiftFactor = u256(1) << ((32 - _bytes) * 8); - m_context << shiftFactor; - if (_leftAligned) - m_context << eth::Instruction::DUP1; - m_context << u256(_offset) << load << eth::Instruction::DIV; - if (_leftAligned) - m_context << eth::Instruction::MUL; - return _bytes; - } + solAssert(_type.getCategory() != Type::Category::ByteArray, "Unable to statically load dynamic type."); + m_context << u256(_offset); + return loadFromMemoryHelper(_type, _fromCalldata, _padToWordBoundaries); } +void CompilerUtils::loadFromMemoryDynamic(Type const& _type, bool _fromCalldata, bool _padToWordBoundaries) +{ + solAssert(_type.getCategory() != Type::Category::ByteArray, "Byte arrays not yet implemented."); + m_context << eth::Instruction::DUP1; + unsigned numBytes = loadFromMemoryHelper(_type, _fromCalldata, _padToWordBoundaries); + // update memory counter + for (unsigned i = 0; i < _type.getSizeOnStack(); ++i) + m_context << eth::swapInstruction(1 + i); + m_context << u256(numBytes) << eth::Instruction::ADD; +} + + unsigned CompilerUtils::storeInMemory(unsigned _offset, Type const& _type, bool _padToWordBoundaries) { solAssert(_type.getCategory() != Type::Category::ByteArray, "Unable to statically store dynamic type."); @@ -79,9 +70,12 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound if (type.getLocation() == ByteArrayType::Location::CallData) { - m_context << eth::Instruction::CALLDATASIZE << u256(0) << eth::Instruction::DUP3 - << eth::Instruction::CALLDATACOPY - << eth::Instruction::CALLDATASIZE << eth::Instruction::ADD; + // stack: target source_offset source_len + m_context << eth::Instruction::DUP1 << eth::Instruction::DUP3 << eth::Instruction::DUP5 + // stack: target source_offset source_len source_len source_offset target + << eth::Instruction::CALLDATACOPY + << eth::Instruction::DUP3 << eth::Instruction::ADD + << eth::Instruction::SWAP2 << eth::Instruction::POP << eth::Instruction::POP; } else { @@ -120,6 +114,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound unsigned numBytes = prepareMemoryStore(_type, _padToWordBoundaries); if (numBytes > 0) { + solAssert(_type.getSizeOnStack() == 1, "Memory store of types with stack size != 1 not implemented."); m_context << eth::Instruction::DUP2 << eth::Instruction::MSTORE; m_context << u256(numBytes) << eth::Instruction::ADD; } @@ -179,29 +174,32 @@ void CompilerUtils::copyByteArrayToStorage(ByteArrayType const& _targetType, { case ByteArrayType::Location::CallData: { - // @todo this does not take length into account. It also assumes that after "CALLDATALENGTH" we only have zeros. + // This also assumes that after "length" we only have zeros, i.e. it cannot be used to + // slice a byte array from calldata. + + // stack: source_offset source_len target_ref // fetch old length and convert to words m_context << eth::Instruction::DUP1 << eth::Instruction::SLOAD; m_context << u256(31) << eth::Instruction::ADD << u256(32) << eth::Instruction::SWAP1 << eth::Instruction::DIV; - // stack here: target_ref target_length_words + // stack here: source_offset source_len target_ref target_length_words // actual array data is stored at SHA3(storage_offset) m_context << eth::Instruction::DUP2; CompilerUtils(m_context).computeHashStatic(); // compute target_data_end m_context << eth::Instruction::DUP1 << eth::Instruction::SWAP2 << eth::Instruction::ADD << eth::Instruction::SWAP1; - // stack here: target_ref target_data_end target_data_ref + // stack here: source_offset source_len target_ref target_data_end target_data_ref // store length (in bytes) - m_context << eth::Instruction::CALLDATASIZE; - m_context << eth::Instruction::DUP1 << eth::Instruction::DUP5 << eth::Instruction::SSTORE; + m_context << eth::Instruction::DUP4 << eth::Instruction::DUP1 << eth::Instruction::DUP5 + << eth::Instruction::SSTORE; // jump to end if length is zero m_context << eth::Instruction::ISZERO; eth::AssemblyItem copyLoopEnd = m_context.newTag(); m_context.appendConditionalJumpTo(copyLoopEnd); // store start offset - m_context << u256(0); - // stack now: target_ref target_data_end target_data_ref calldata_offset + m_context << eth::Instruction::DUP5; + // stack now: source_offset source_len target_ref target_data_end target_data_ref calldata_offset eth::AssemblyItem copyLoopStart = m_context.newTag(); m_context << copyLoopStart // copy from calldata and store @@ -212,16 +210,18 @@ void CompilerUtils::copyByteArrayToStorage(ByteArrayType const& _targetType, // increment calldata_offset by 32 << eth::Instruction::SWAP1 << u256(32) << eth::Instruction::ADD // check for loop condition - << eth::Instruction::DUP1 << eth::Instruction::CALLDATASIZE << eth::Instruction::GT; + << eth::Instruction::DUP1 << eth::Instruction::DUP6 << eth::Instruction::GT; m_context.appendConditionalJumpTo(copyLoopStart); m_context << eth::Instruction::POP; m_context << copyLoopEnd; // now clear leftover bytes of the old value - // stack now: target_ref target_data_end target_data_ref + // stack now: source_offset source_len target_ref target_data_end target_data_ref clearStorageLoop(); + // stack now: source_offset source_len target_ref target_data_end - m_context << eth::Instruction::POP; + m_context << eth::Instruction::POP << eth::Instruction::SWAP2 + << eth::Instruction::POP << eth::Instruction::POP; break; } case ByteArrayType::Location::Storage: @@ -289,6 +289,30 @@ void CompilerUtils::copyByteArrayToStorage(ByteArrayType const& _targetType, } } +unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWordBoundaries) +{ + unsigned _encodedSize = _type.getCalldataEncodedSize(); + unsigned numBytes = _padToWordBoundaries ? getPaddedSize(_encodedSize) : _encodedSize; + bool leftAligned = _type.getCategory() == Type::Category::String; + if (numBytes == 0) + m_context << eth::Instruction::POP << u256(0); + else + { + solAssert(numBytes <= 32, "Static memory load of more than 32 bytes requested."); + m_context << (_fromCalldata ? eth::Instruction::CALLDATALOAD : eth::Instruction::MLOAD); + if (numBytes != 32) + { + // add leading or trailing zeros by dividing/multiplying depending on alignment + u256 shiftFactor = u256(1) << ((32 - numBytes) * 8); + m_context << shiftFactor << eth::Instruction::SWAP1 << eth::Instruction::DIV; + if (leftAligned) + m_context << shiftFactor << eth::Instruction::MUL; + } + } + + return numBytes; +} + void CompilerUtils::clearByteArray(ByteArrayType const& _type) const { solAssert(_type.getLocation() == ByteArrayType::Location::Storage, ""); diff --git a/libsolidity/CompilerUtils.h b/libsolidity/CompilerUtils.h index fe28ceadf..5369d3bf2 100644 --- a/libsolidity/CompilerUtils.h +++ b/libsolidity/CompilerUtils.h @@ -37,14 +37,16 @@ public: /// Loads data from memory to the stack. /// @param _offset offset in memory (or calldata) - /// @param _bytes number of bytes to load - /// @param _leftAligned if true, store left aligned on stack (otherwise right aligned) + /// @param _type data type to load /// @param _fromCalldata if true, load from calldata, not from memory /// @param _padToWordBoundaries if true, assume the data is padded to word (32 byte) boundaries - /// @returns the number of bytes consumed in memory (can be different from _bytes if - /// _padToWordBoundaries is true) - unsigned loadFromMemory(unsigned _offset, unsigned _bytes = 32, bool _leftAligned = false, - bool _fromCalldata = false, bool _padToWordBoundaries = false); + /// @returns the number of bytes consumed in memory. + unsigned loadFromMemory(unsigned _offset, Type const& _type = IntegerType(256), + bool _fromCalldata = false, bool _padToWordBoundaries = false); + /// Dynamic version of @see loadFromMemory, expects the memory offset on the stack. + /// Stack pre: memory_offset + /// Stack post: value... (memory_offset+length) + void loadFromMemoryDynamic(Type const& _type, bool _fromCalldata = false, bool _padToWordBoundaries = true); /// Stores data from stack in memory. /// @param _offset offset in memory /// @param _type type of the data on the stack @@ -93,6 +95,8 @@ public: private: /// Prepares the given type for storing in memory by shifting it if necessary. unsigned prepareMemoryStore(Type const& _type, bool _padToWordBoundaries) const; + /// Loads type from memory assuming memory offset is on stack top. + unsigned loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWordBoundaries); /// Appends a loop that clears a sequence of storage slots (excluding end). /// Stack pre: end_ref start_ref /// Stack post: end_ref diff --git a/libsolidity/DeclarationContainer.cpp b/libsolidity/DeclarationContainer.cpp index 2e810a4cf..2594d4281 100644 --- a/libsolidity/DeclarationContainer.cpp +++ b/libsolidity/DeclarationContainer.cpp @@ -28,14 +28,19 @@ namespace dev namespace solidity { -bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, bool _update) +bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, bool _invisible, bool _update) { - if (_declaration.getName().empty()) + ASTString const& name(_declaration.getName()); + if (name.empty()) return true; - if (!_update && m_declarations.find(_declaration.getName()) != m_declarations.end()) + if (!_update && (m_declarations.count(name) || m_invisibleDeclarations.count(name))) return false; - m_declarations[_declaration.getName()] = &_declaration; + + if (_invisible) + m_invisibleDeclarations.insert(name); + else + m_declarations[name] = &_declaration; return true; } diff --git a/libsolidity/DeclarationContainer.h b/libsolidity/DeclarationContainer.h index 1216fcef2..f70881f5b 100644 --- a/libsolidity/DeclarationContainer.h +++ b/libsolidity/DeclarationContainer.h @@ -23,6 +23,7 @@ #pragma once #include +#include #include #include @@ -43,8 +44,10 @@ public: DeclarationContainer const* _enclosingContainer = nullptr): m_enclosingDeclaration(_enclosingDeclaration), m_enclosingContainer(_enclosingContainer) {} /// Registers the declaration in the scope unless its name is already declared or the name is empty. + /// @param _invisible if true, registers the declaration, reports name clashes but does not return it in @a resolveName + /// @param _update if true, replaces a potential declaration that is already present /// @returns false if the name was already declared. - bool registerDeclaration(Declaration const& _declaration, bool _update = false); + bool registerDeclaration(Declaration const& _declaration, bool _invisible = false, bool _update = false); Declaration const* resolveName(ASTString const& _name, bool _recursive = false) const; Declaration const* getEnclosingDeclaration() const { return m_enclosingDeclaration; } std::map const& getDeclarations() const { return m_declarations; } @@ -53,6 +56,7 @@ private: Declaration const* m_enclosingDeclaration; DeclarationContainer const* m_enclosingContainer; std::map m_declarations; + std::set m_invisibleDeclarations; }; } diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 0f0e94f21..3bf1c8c93 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -475,9 +475,7 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) else if (member == "gasprice") m_context << eth::Instruction::GASPRICE; else if (member == "data") - { - // nothing to store on the stack - } + m_context << u256(0) << eth::Instruction::CALLDATASIZE; else BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown magic member.")); break; @@ -510,6 +508,7 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) m_context << m_context.getFunctionEntryLabel(*function).pushTag(); return; } + solAssert(false, "Function not found in member access."); } else if (auto enumType = dynamic_cast(type.getActualType().get())) m_context << enumType->getMemberValue(_memberAccess.getMemberName()); @@ -518,7 +517,19 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) case Type::Category::ByteArray: { solAssert(member == "length", "Illegal bytearray member."); - m_context << eth::Instruction::SLOAD; + auto const& type = dynamic_cast(*_memberAccess.getExpression().getType()); + switch (type.getLocation()) + { + case ByteArrayType::Location::CallData: + m_context << eth::Instruction::SWAP1 << eth::Instruction::POP; + break; + case ByteArrayType::Location::Storage: + m_context << eth::Instruction::SLOAD; + break; + default: + solAssert(false, "Unsupported byte array location."); + break; + } break; } default: @@ -885,11 +896,8 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio m_context << eth::Instruction::POP; m_context << eth::Instruction::POP; // pop contract address - if (retSize > 0) - { - bool const c_leftAligned = firstType->getCategory() == Type::Category::String; - CompilerUtils(m_context).loadFromMemory(0, retSize, c_leftAligned, false, true); - } + if (firstType) + CompilerUtils(m_context).loadFromMemory(0, *firstType, false, true); } void ExpressionCompiler::appendArgumentsCopyToMemory(vector> const& _arguments, diff --git a/libsolidity/NameAndTypeResolver.cpp b/libsolidity/NameAndTypeResolver.cpp index dbe5693a8..ea70b65b4 100644 --- a/libsolidity/NameAndTypeResolver.cpp +++ b/libsolidity/NameAndTypeResolver.cpp @@ -86,7 +86,7 @@ void NameAndTypeResolver::checkTypeRequirements(ContractDefinition& _contract) void NameAndTypeResolver::updateDeclaration(Declaration const& _declaration) { - m_scopes[nullptr].registerDeclaration(_declaration, true); + m_scopes[nullptr].registerDeclaration(_declaration, false, true); solAssert(_declaration.getScope() == nullptr, "Updated declaration outside global scope."); } @@ -110,8 +110,9 @@ void NameAndTypeResolver::importInheritedScope(ContractDefinition const& _base) for (auto const& nameAndDeclaration: iterator->second.getDeclarations()) { Declaration const* declaration = nameAndDeclaration.second; - // Import if it was declared in the base and is not the constructor - if (declaration->getScope() == &_base && declaration->getName() != _base.getName()) + // Import if it was declared in the base, is not the constructor and is visible in derived classes + if (declaration->getScope() == &_base && declaration->getName() != _base.getName() && + declaration->isVisibleInDerivedContracts()) m_currentScope->registerDeclaration(*declaration); } } @@ -308,7 +309,7 @@ void DeclarationRegistrationHelper::closeCurrentScope() void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaration, bool _opensScope) { - if (!m_scopes[m_currentScope].registerDeclaration(_declaration)) + if (!m_scopes[m_currentScope].registerDeclaration(_declaration, !_declaration.isVisibleInContract())) BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_declaration.getLocation()) << errinfo_comment("Identifier already declared.")); //@todo the exception should also contain the location of the first declaration diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index c96593f64..cf57ca50e 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -190,6 +190,8 @@ Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token) visibility = Declaration::Visibility::Protected; else if (_token == Token::Private) visibility = Declaration::Visibility::Private; + else if (_token == Token::External) + visibility = Declaration::Visibility::External; else solAssert(false, "Invalid visibility specifier."); m_scanner->next(); @@ -306,7 +308,7 @@ ASTPointer Parser::parseVariableDeclaration(VarDeclParserOp ASTPointer identifier; Token::Value token = m_scanner->getCurrentToken(); Declaration::Visibility visibility(Declaration::Visibility::Default); - if (_options.isStateVariable && Token::isVisibilitySpecifier(token)) + if (_options.isStateVariable && Token::isVariableVisibilitySpecifier(token)) visibility = parseVisibilitySpecifier(token); if (_options.allowIndexed && token == Token::Indexed) { diff --git a/libsolidity/Token.h b/libsolidity/Token.h index 3e599a6ee..7bf8a7ef0 100644 --- a/libsolidity/Token.h +++ b/libsolidity/Token.h @@ -150,6 +150,7 @@ namespace solidity K(Do, "do", 0) \ K(Else, "else", 0) \ K(Event, "event", 0) \ + K(External, "external", 0) \ K(Is, "is", 0) \ K(Indexed, "indexed", 0) \ K(For, "for", 0) \ @@ -378,7 +379,8 @@ public: static bool isUnaryOp(Value op) { return (Not <= op && op <= Delete) || op == Add || op == Sub; } static bool isCountOp(Value op) { return op == Inc || op == Dec; } static bool isShiftOp(Value op) { return (SHL <= op) && (op <= SHR); } - static bool isVisibilitySpecifier(Value op) { return op == Public || op == Private || op == Protected; } + static bool isVisibilitySpecifier(Value op) { return isVariableVisibilitySpecifier(op) || op == External; } + static bool isVariableVisibilitySpecifier(Value op) { return op == Public || op == Private || op == Protected; } static bool isEtherSubdenomination(Value op) { return op == SubWei || op == SubSzabo || op == SubFinney || op == Token::SubEther; } // Returns a string corresponding to the JS token string diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 5d753645c..d2f0e9bfd 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -540,12 +540,19 @@ bool ByteArrayType::operator==(Type const& _other) const unsigned ByteArrayType::getSizeOnStack() const { if (m_location == Location::CallData) - return 0; + // offset, length (stack top) + return 2; else + // offset return 1; } -const MemberList ByteArrayType::s_byteArrayMemberList = MemberList({{"length", make_shared(256)}}); +shared_ptr ByteArrayType::copyForLocation(ByteArrayType::Location _location) const +{ + return make_shared(_location); +} + +const MemberList ByteArrayType::s_byteArrayMemberList = MemberList({{"length", make_shared(256)}}); bool ContractType::operator==(Type const& _other) const { @@ -572,7 +579,8 @@ MemberList const& ContractType::getMembers() const { for (ContractDefinition const* base: m_contract.getLinearizedBaseContracts()) for (ASTPointer const& function: base->getDefinedFunctions()) - if (!function->isConstructor() && !function->getName().empty()) + if (!function->isConstructor() && !function->getName().empty() && + function->isVisibleInDerivedContracts()) members.insert(make_pair(function->getName(), make_shared(*function, true))); } else @@ -769,7 +777,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): } FunctionType::FunctionType(const EventDefinition& _event): - m_location(Location::Event), m_declaration(&_event) + m_location(Location::Event), m_isConstant(true), m_declaration(&_event) { TypePointers params; vector paramNames; @@ -957,10 +965,10 @@ MemberList const& TypeType::getMembers() const ContractDefinition const& contract = dynamic_cast(*m_actualType).getContractDefinition(); vector currentBases = m_currentContract->getLinearizedBaseContracts(); if (find(currentBases.begin(), currentBases.end(), &contract) != currentBases.end()) - // We are accessing the type of a base contract, so add all public and private + // We are accessing the type of a base contract, so add all public and protected // functions. Note that this does not add inherited functions on purpose. for (ASTPointer const& f: contract.getDefinedFunctions()) - if (!f->isConstructor() && !f->getName().empty()) + if (!f->isConstructor() && !f->getName().empty() && f->isVisibleInDerivedContracts()) members[f->getName()] = make_shared(*f); } else if (m_actualType->getCategory() == Category::Enum) diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 3b4eee57f..b66857f0c 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -122,6 +122,8 @@ public: /// is not a simple big-endian encoding or the type cannot be stored in calldata. /// Note that irrespective of this size, each calldata element is padded to a multiple of 32 bytes. virtual unsigned getCalldataEncodedSize() const { return 0; } + /// @returns true if the type is dynamically encoded in calldata + virtual bool isDynamicallySized() const { return false; } /// @returns number of bytes required to hold this value in storage. /// For dynamically "allocated" types, it returns the size of the statically allocated head, virtual u256 getStorageSize() const { return 1; } @@ -289,12 +291,17 @@ public: virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; virtual bool operator==(const Type& _other) const override; + virtual bool isDynamicallySized() const { return true; } virtual unsigned getSizeOnStack() const override; virtual std::string toString() const override { return "bytes"; } virtual MemberList const& getMembers() const override { return s_byteArrayMemberList; } Location getLocation() const { return m_location; } + /// @returns a copy of this type with location changed to @a _location + /// @todo this might move as far up as Type later + std::shared_ptr copyForLocation(Location _location) const; + private: Location m_location; static const MemberList s_byteArrayMemberList; diff --git a/libweb3jsonrpc/CMakeLists.txt b/libweb3jsonrpc/CMakeLists.txt index 34df1633a..867dd7e7e 100644 --- a/libweb3jsonrpc/CMakeLists.txt +++ b/libweb3jsonrpc/CMakeLists.txt @@ -9,8 +9,8 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) -include_directories(..) -include_directories(${JSONCPP_INCLUDE_DIRS}) +include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) +include_directories(BEFORE ..) include_directories(${MHD_INCLUDE_DIRS}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIRS}) diff --git a/libweb3jsonrpc/WebThreeStubServerBase.cpp b/libweb3jsonrpc/WebThreeStubServerBase.cpp index 27b8268da..7e15ada90 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.cpp +++ b/libweb3jsonrpc/WebThreeStubServerBase.cpp @@ -367,6 +367,26 @@ double WebThreeStubServerBase::eth_countAt(string const& _address) return (double)(uint64_t)client()->countAt(jsToAddress(_address), client()->getDefault()); } +double WebThreeStubServerBase::eth_transactionCountByHash(std::string const& _hash) +{ + return client()->transactionCount(jsToFixed<32>(_hash)); +} + +double WebThreeStubServerBase::eth_transactionCountByNumber(int _number) +{ + return client()->transactionCount(client()->hashFromNumber(_number)); +} + +double WebThreeStubServerBase::eth_uncleCountByHash(std::string const& _hash) +{ + return client()->transactionCount(jsToFixed<32>(_hash)); +} + +double WebThreeStubServerBase::eth_uncleCountByNumber(int _number) +{ + return client()->transactionCount(client()->hashFromNumber(_number)); +} + int WebThreeStubServerBase::eth_defaultBlock() { return client()->getDefault(); @@ -613,6 +633,29 @@ Json::Value WebThreeStubServerBase::shh_changed(int _id) return ret; } +Json::Value WebThreeStubServerBase::shh_getMessages(int _id) +{ + Json::Value ret(Json::arrayValue); + auto pub = m_shhWatches[_id]; + if (!pub || m_ids.count(pub)) + for (h256 const& h: face()->watchMessages(_id)) + { + auto e = face()->envelope(h); + shh::Message m; + if (pub) + { + cwarn << "Silently decrypting message from identity" << pub.abridged() << ": User validation hook goes here."; + m = e.open(face()->fullTopic(_id), m_ids[pub]); + } + else + m = e.open(face()->fullTopic(_id)); + if (!m) + continue; + ret.append(toJson(h, e, m)); + } + return ret; +} + int WebThreeStubServerBase::shh_newFilter(Json::Value const& _json) { auto w = toWatch(_json); diff --git a/libweb3jsonrpc/WebThreeStubServerBase.h b/libweb3jsonrpc/WebThreeStubServerBase.h index 005ac4130..ec83c9797 100644 --- a/libweb3jsonrpc/WebThreeStubServerBase.h +++ b/libweb3jsonrpc/WebThreeStubServerBase.h @@ -76,6 +76,10 @@ public: virtual std::string eth_coinbase(); virtual Json::Value eth_compilers(); virtual double eth_countAt(std::string const& _address); + virtual double eth_transactionCountByHash(std::string const& _hash); + virtual double eth_transactionCountByNumber(int _number); + virtual double eth_uncleCountByHash(std::string const& _hash); + virtual double eth_uncleCountByNumber(int _number); virtual int eth_defaultBlock(); virtual std::string eth_gasPrice(); virtual Json::Value eth_filterLogs(int _id); @@ -113,6 +117,7 @@ public: virtual std::string shh_addToGroup(std::string const& _group, std::string const& _who); virtual Json::Value shh_changed(int _id); + virtual Json::Value shh_getMessages(int _id); virtual bool shh_haveIdentity(std::string const& _id); virtual int shh_newFilter(Json::Value const& _json); virtual std::string shh_newGroup(std::string const& _id, std::string const& _who); diff --git a/libweb3jsonrpc/abstractwebthreestubserver.h b/libweb3jsonrpc/abstractwebthreestubserver.h index 5bade41f6..53d7f856d 100644 --- a/libweb3jsonrpc/abstractwebthreestubserver.h +++ b/libweb3jsonrpc/abstractwebthreestubserver.h @@ -29,6 +29,10 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(jsonrpc::Procedure("eth_stateAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING,"param2",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_stateAtI); this->bindAndAddMethod(jsonrpc::Procedure("eth_storageAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_OBJECT, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_storageAtI); this->bindAndAddMethod(jsonrpc::Procedure("eth_countAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_countAtI); + this->bindAndAddMethod(jsonrpc::Procedure("eth_transactionCountByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_transactionCountByHashI); + this->bindAndAddMethod(jsonrpc::Procedure("eth_transactionCountByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_transactionCountByNumberI); + this->bindAndAddMethod(jsonrpc::Procedure("eth_uncleCountByHash", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_uncleCountByHashI); + this->bindAndAddMethod(jsonrpc::Procedure("eth_uncleCountByNumber", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_REAL, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::eth_uncleCountByNumberI); this->bindAndAddMethod(jsonrpc::Procedure("eth_codeAt", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_STRING, NULL), &AbstractWebThreeStubServer::eth_codeAtI); this->bindAndAddMethod(jsonrpc::Procedure("eth_transact", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_transactI); this->bindAndAddMethod(jsonrpc::Procedure("eth_call", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_STRING, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::eth_callI); @@ -63,6 +67,7 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServerbindAndAddMethod(jsonrpc::Procedure("shh_newFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_INTEGER, "param1",jsonrpc::JSON_OBJECT, NULL), &AbstractWebThreeStubServer::shh_newFilterI); this->bindAndAddMethod(jsonrpc::Procedure("shh_uninstallFilter", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_BOOLEAN, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::shh_uninstallFilterI); this->bindAndAddMethod(jsonrpc::Procedure("shh_changed", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::shh_changedI); + this->bindAndAddMethod(jsonrpc::Procedure("shh_getMessages", jsonrpc::PARAMS_BY_POSITION, jsonrpc::JSON_ARRAY, "param1",jsonrpc::JSON_INTEGER, NULL), &AbstractWebThreeStubServer::shh_getMessagesI); } inline virtual void web3_sha3I(const Json::Value &request, Json::Value &response) @@ -141,6 +146,22 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServereth_countAt(request[0u].asString()); } + inline virtual void eth_transactionCountByHashI(const Json::Value &request, Json::Value &response) + { + response = this->eth_transactionCountByHash(request[0u].asString()); + } + inline virtual void eth_transactionCountByNumberI(const Json::Value &request, Json::Value &response) + { + response = this->eth_transactionCountByNumber(request[0u].asInt()); + } + inline virtual void eth_uncleCountByHashI(const Json::Value &request, Json::Value &response) + { + response = this->eth_uncleCountByHash(request[0u].asString()); + } + inline virtual void eth_uncleCountByNumberI(const Json::Value &request, Json::Value &response) + { + response = this->eth_uncleCountByNumber(request[0u].asInt()); + } inline virtual void eth_codeAtI(const Json::Value &request, Json::Value &response) { response = this->eth_codeAt(request[0u].asString()); @@ -281,6 +302,10 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServershh_changed(request[0u].asInt()); } + inline virtual void shh_getMessagesI(const Json::Value &request, Json::Value &response) + { + response = this->shh_getMessages(request[0u].asInt()); + } virtual std::string web3_sha3(const std::string& param1) = 0; virtual std::string eth_coinbase() = 0; virtual bool eth_setCoinbase(const std::string& param1) = 0; @@ -298,6 +323,10 @@ class AbstractWebThreeStubServer : public jsonrpc::AbstractServer("QBigInt*"); qRegisterMetaType("QIntType*"); @@ -136,9 +136,12 @@ void ClientModel::mine() }); } -QString ClientModel::contractAddress() const +QVariantMap ClientModel::contractAddresses() const { - return QString::fromStdString(dev::toJS(m_contractAddress)); + QVariantMap res; + for (auto const& c: m_contractAddresses) + res.insert(c.first, QString::fromStdString(dev::toJS(c.second))); + return res; } void ClientModel::debugDeployment() @@ -155,8 +158,8 @@ void ClientModel::setupState(QVariantMap _state) for (auto const& t: transactions) { QVariantMap transaction = t.toMap(); + QString contractId = transaction.value("contractId").toString(); QString functionId = transaction.value("functionId").toString(); - u256 gas = boost::get(qvariant_cast(transaction.value("gas"))->internalValue()); u256 value = (qvariant_cast(transaction.value("value")))->toU256Wei(); u256 gasPrice = (qvariant_cast(transaction.value("gasPrice")))->toU256Wei(); @@ -164,7 +167,9 @@ void ClientModel::setupState(QVariantMap _state) bool isStdContract = (transaction.value("stdContract").toBool()); if (isStdContract) { - TransactionSettings transactionSettings(functionId, transaction.value("url").toString()); + if (contractId.isEmpty()) //TODO: This is to support old project files, remove later + contractId = functionId; + TransactionSettings transactionSettings(contractId, transaction.value("url").toString()); transactionSettings.gasPrice = 10000000000000; transactionSettings.gas = 125000; transactionSettings.value = 0; @@ -172,8 +177,10 @@ void ClientModel::setupState(QVariantMap _state) } else { + if (contractId.isEmpty() && m_context->codeModel()->hasContract()) //TODO: This is to support old project files, remove later + contractId = m_context->codeModel()->contracts().keys()[0]; QVariantList qParams = transaction.value("qType").toList(); - TransactionSettings transactionSettings(functionId, value, gas, gasPrice); + TransactionSettings transactionSettings(contractId, functionId, value, gas, gasPrice); for (QVariant const& variant: qParams) { @@ -181,7 +188,7 @@ void ClientModel::setupState(QVariantMap _state) transactionSettings.parameterValues.push_back(param); } - if (transaction.value("executeConstructor").toBool()) + if (contractId == functionId || functionId == "Constructor") transactionSettings.functionId.clear(); transactionSequence.push_back(transactionSettings); @@ -194,8 +201,6 @@ void ClientModel::executeSequence(std::vector const& _seque { if (m_running) BOOST_THROW_EXCEPTION(ExecutionStateException()); - CompilationResult* compilerRes = m_context->codeModel()->code(); - std::shared_ptr contractDef = compilerRes->sharedContract(); m_running = true; emit runStarted(); @@ -206,25 +211,26 @@ void ClientModel::executeSequence(std::vector const& _seque { try { - bytes contractCode = compilerRes->bytes(); m_client->resetState(_balance); onStateReset(); for (TransactionSettings const& transaction: _sequence) { ContractCallDataEncoder encoder; - QFunctionDefinition const* f = nullptr; if (!transaction.stdContractUrl.isEmpty()) { //std contract - dev::bytes const& stdContractCode = m_context->codeModel()->getStdContractCode(transaction.functionId, transaction.stdContractUrl); + dev::bytes const& stdContractCode = m_context->codeModel()->getStdContractCode(transaction.contractId, transaction.stdContractUrl); Address address = deployContract(stdContractCode, transaction); - m_stdContractAddresses[transaction.functionId] = address; - m_stdContractNames[address] = transaction.functionId; + m_stdContractAddresses[transaction.contractId] = address; + m_stdContractNames[address] = transaction.contractId; } else { //encode data - f = nullptr; + CompiledContract const& compilerRes = m_context->codeModel()->contract(transaction.contractId); + QFunctionDefinition const* f = nullptr; + bytes contractCode = compilerRes.bytes(); + std::shared_ptr contractDef = compilerRes.sharedContract(); if (transaction.functionId.isEmpty()) f = contractDef->constructor(); else @@ -240,24 +246,31 @@ void ClientModel::executeSequence(std::vector const& _seque encoder.encode(f); for (int p = 0; p < transaction.parameterValues.size(); p++) { - if (f->parametersList().at(p)->type() != transaction.parameterValues.at(p)->declaration()->type()) - BOOST_THROW_EXCEPTION(ParameterChangedException() << FunctionName(f->parametersList().at(p)->type().toStdString())); + if (f->parametersList().size() <= p || f->parametersList().at(p)->type() != transaction.parameterValues.at(p)->declaration()->type()) + BOOST_THROW_EXCEPTION(ParameterChangedException() << FunctionName(transaction.functionId.toStdString())); encoder.push(transaction.parameterValues.at(p)->encodeValue()); } - if (transaction.functionId.isEmpty()) + if (transaction.functionId.isEmpty() || transaction.functionId == transaction.contractId) { bytes param = encoder.encodedData(); contractCode.insert(contractCode.end(), param.begin(), param.end()); Address newAddress = deployContract(contractCode, transaction); - if (newAddress != m_contractAddress) + auto contractAddressIter = m_contractAddresses.find(transaction.contractId); + if (contractAddressIter == m_contractAddresses.end() || newAddress != contractAddressIter->second) { - m_contractAddress = newAddress; - contractAddressChanged(); + m_contractAddresses[transaction.contractId] = newAddress; + m_contractNames[newAddress] = transaction.contractId; + contractAddressesChanged(); } } else - callContract(m_contractAddress, encoder.encodedData(), transaction); + { + auto contractAddressIter = m_contractAddresses.find(transaction.contractId); + if (contractAddressIter == m_contractAddresses.end()) + BOOST_THROW_EXCEPTION(dev::Exception() << dev::errinfo_comment("Contract not deployed: " + transaction.contractId.toStdString())); + callContract(contractAddressIter->second, encoder.encodedData(), transaction); + } } onNewTransaction(); } @@ -338,7 +351,8 @@ void ClientModel::callContract(Address const& _contract, bytes const& _data, Tra void ClientModel::onStateReset() { - m_contractAddress = dev::Address(); + m_contractAddresses.clear(); + m_contractNames.clear(); m_stdContractAddresses.clear(); m_stdContractNames.clear(); emit stateCleared(); @@ -389,14 +403,16 @@ void ClientModel::onNewTransaction() if (creation) returned = QString::fromStdString(toJS(tr.contractAddress)); - if (m_contractAddress != 0 && (tr.address == m_contractAddress || tr.contractAddress == m_contractAddress)) + Address contractAddress = tr.address != 0 ? tr.address : tr.contractAddress; + auto contractAddressIter = m_contractNames.find(contractAddress); + if (contractAddressIter != m_contractNames.end()) { - auto compilerRes = m_context->codeModel()->code(); - QContractDefinition* def = compilerRes->contract(); + CompiledContract const& compilerRes = m_context->codeModel()->contract(contractAddressIter->second); + const QContractDefinition* def = compilerRes.contract(); contract = def->name(); if (abi) { - QFunctionDefinition* funcDef = def->getFunction(functionHash); + QFunctionDefinition const* funcDef = def->getFunction(functionHash); if (funcDef) { function = funcDef->name(); diff --git a/mix/ClientModel.h b/mix/ClientModel.h index 530dc50cf..dda60cb10 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -46,13 +46,13 @@ class QVariableDefinition; struct TransactionSettings { TransactionSettings() {} - TransactionSettings(QString const& _functionId, u256 _value, u256 _gas, u256 _gasPrice): - functionId(_functionId), value(_value), gas(_gas), gasPrice(_gasPrice) {} - TransactionSettings(u256 _value, u256 _gas, u256 _gasPrice): - value(_value), gas(_gas), gasPrice(_gasPrice) {} + TransactionSettings(QString const& _contractId, QString const& _functionId, u256 _value, u256 _gas, u256 _gasPrice): + contractId(_contractId), functionId(_functionId), value(_value), gas(_gas), gasPrice(_gasPrice) {} TransactionSettings(QString const& _stdContractName, QString const& _stdContractUrl): - functionId(_stdContractName), stdContractUrl(_stdContractUrl) {} + contractId(_stdContractName), stdContractUrl(_stdContractUrl) {} + /// Contract name + QString contractId; /// Contract function name QString functionId; /// Transaction value @@ -121,8 +121,8 @@ public: Q_PROPERTY(bool running MEMBER m_running NOTIFY runStateChanged) /// @returns true if currently mining Q_PROPERTY(bool mining MEMBER m_mining NOTIFY miningStateChanged) - /// @returns address of the last executed contract - Q_PROPERTY(QString contractAddress READ contractAddress NOTIFY contractAddressChanged) + /// @returns deployed contracts addresses + Q_PROPERTY(QVariantMap contractAddresses READ contractAddresses NOTIFY contractAddressesChanged) /// ethereum.js RPC request entry point /// @param _message RPC request in Json format /// @returns RPC response in Json format @@ -161,7 +161,7 @@ signals: /// @param _message Error message void runFailed(QString const& _message); /// Contract address changed - void contractAddressChanged(); + void contractAddressesChanged(); /// Execution state changed void newBlock(); /// Execution state changed @@ -177,7 +177,7 @@ signals: void stateCleared(); private: - QString contractAddress() const; + QVariantMap contractAddresses() const; void executeSequence(std::vector const& _sequence, u256 _balance); dev::Address deployContract(bytes const& _code, TransactionSettings const& _tr = TransactionSettings()); void callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr); @@ -191,7 +191,8 @@ private: std::unique_ptr m_client; std::unique_ptr m_rpcConnector; std::unique_ptr m_web3Server; - Address m_contractAddress; + std::map m_contractAddresses; + std::map m_contractNames; std::map m_stdContractAddresses; std::map m_stdContractNames; }; diff --git a/mix/CodeHighlighter.cpp b/mix/CodeHighlighter.cpp index d76d8b73e..86dfe9e5d 100644 --- a/mix/CodeHighlighter.cpp +++ b/mix/CodeHighlighter.cpp @@ -119,7 +119,7 @@ void CodeHighlighter::processComments(std::string const& _source) //add single line comment int start = i; i += 2; - while (_source[i] != '\n' && i < size) + while (i < size && _source[i] != '\n') ++i; m_formats.push_back(FormatRange(CodeHighlighterSettings::Comment, start, i - start)); } diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index aae9dac86..7a38594ce 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -21,6 +21,7 @@ */ #include +#include #include #include #include @@ -38,51 +39,31 @@ using namespace dev::mix; -void BackgroundWorker::queueCodeChange(int _jobId, QString const& _content) +const std::set c_predefinedContracts = + { "Config", "Coin", "CoinReg", "coin", "service", "owned", "mortal", "NameReg", "named", "std", "configUser" }; + +void BackgroundWorker::queueCodeChange(int _jobId) { - m_model->runCompilationJob(_jobId, _content); + m_model->runCompilationJob(_jobId); } -CompilationResult::CompilationResult(): - QObject(nullptr), - m_successful(false), - m_codeHash(qHash(QString())), - m_contract(new QContractDefinition()), - m_contractInterface("[]"), - m_codeHighlighter(new CodeHighlighter()) -{} - -CompilationResult::CompilationResult(const dev::solidity::CompilerStack& _compiler): +CompiledContract::CompiledContract(const dev::solidity::CompilerStack& _compiler, QString const& _contractName, QString const& _source): QObject(nullptr), - m_successful(true), - m_codeHash(qHash(QString())) + m_sourceHash(qHash(_source)) { - if (!_compiler.getContractNames().empty()) - { - auto const& contractDefinition = _compiler.getContractDefinition(std::string()); - m_contract.reset(new QContractDefinition(&contractDefinition)); - m_bytes = _compiler.getBytecode(); - dev::solidity::InterfaceHandler interfaceHandler; - m_contractInterface = QString::fromStdString(*interfaceHandler.getABIInterface(contractDefinition)); - if (m_contractInterface.isEmpty()) - m_contractInterface = "[]"; - } - else - m_contract.reset(new QContractDefinition()); + auto const& contractDefinition = _compiler.getContractDefinition(_contractName.toStdString()); + m_contract.reset(new QContractDefinition(&contractDefinition)); + QQmlEngine::setObjectOwnership(m_contract.get(), QQmlEngine::CppOwnership); + m_bytes = _compiler.getBytecode(_contractName.toStdString()); + dev::solidity::InterfaceHandler interfaceHandler; + m_contractInterface = QString::fromStdString(*interfaceHandler.getABIInterface(contractDefinition)); + if (m_contractInterface.isEmpty()) + m_contractInterface = "[]"; + if (contractDefinition.getLocation().sourceName.get()) + m_documentId = QString::fromStdString(*contractDefinition.getLocation().sourceName); } -CompilationResult::CompilationResult(CompilationResult const& _prev, QString const& _compilerMessage): - QObject(nullptr), - m_successful(false), - m_codeHash(qHash(QString())), - m_contract(_prev.m_contract), - m_compilerMessage(_compilerMessage), - m_bytes(_prev.m_bytes), - m_contractInterface(_prev.m_contractInterface), - m_codeHighlighter(_prev.m_codeHighlighter) -{} - -QString CompilationResult::codeHex() const +QString CompiledContract::codeHex() const { return QString::fromStdString(toJS(m_bytes)); } @@ -90,27 +71,26 @@ QString CompilationResult::codeHex() const CodeModel::CodeModel(QObject* _parent): QObject(_parent), m_compiling(false), - m_result(new CompilationResult()), m_codeHighlighterSettings(new CodeHighlighterSettings()), m_backgroundWorker(this), m_backgroundJobId(0) { + m_backgroundThread.start(); m_backgroundWorker.moveToThread(&m_backgroundThread); connect(this, &CodeModel::scheduleCompilationJob, &m_backgroundWorker, &BackgroundWorker::queueCodeChange, Qt::QueuedConnection); - connect(this, &CodeModel::compilationCompleteInternal, this, &CodeModel::onCompilationComplete, Qt::QueuedConnection); - qRegisterMetaType("CompilationResult*"); + qRegisterMetaType("CompiledContract*"); qRegisterMetaType("QContractDefinition*"); qRegisterMetaType("QFunctionDefinition*"); qRegisterMetaType("QVariableDeclaration*"); qmlRegisterType("org.ethereum.qml", 1, 0, "QFunctionDefinition"); qmlRegisterType("org.ethereum.qml", 1, 0, "QVariableDeclaration"); - m_backgroundThread.start(); } CodeModel::~CodeModel() { stop(); disconnect(this); + releaseContracts(); } void CodeModel::stop() @@ -120,80 +100,133 @@ void CodeModel::stop() m_backgroundThread.wait(); } -void CodeModel::registerCodeChange(QString const& _code) +void CodeModel::reset(QVariantMap const& _documents) { + ///@todo: cancel bg job + Guard l(x_contractMap); + releaseContracts(); + Guard pl(x_pendingContracts); + m_pendingContracts.clear(); + + for (QVariantMap::const_iterator d = _documents.cbegin(); d != _documents.cend(); ++d) + m_pendingContracts[d.key()] = d.value().toString(); // launch the background thread - uint hash = qHash(_code); - if (m_result->m_codeHash == hash) - return; - m_backgroundJobId++; m_compiling = true; emit stateChanged(); - emit scheduleCompilationJob(m_backgroundJobId, _code); + emit scheduleCompilationJob(++m_backgroundJobId); } -void CodeModel::runCompilationJob(int _jobId, QString const& _code) +void CodeModel::registerCodeChange(QString const& _documentId, QString const& _code) { - if (_jobId != m_backgroundJobId) - return; //obsolete job + { + Guard l(x_contractMap); + CompiledContract* contract = m_contractMap.value(_documentId); + if (contract != nullptr && contract->m_sourceHash == qHash(_code)) + return; - solidity::CompilerStack cs(true); - std::unique_ptr result; + Guard pl(x_pendingContracts); + m_pendingContracts[_documentId] = _code; + } + + // launch the background thread + m_compiling = true; + emit stateChanged(); + emit scheduleCompilationJob(++m_backgroundJobId); +} + +QVariantMap CodeModel::contracts() const +{ + QVariantMap result; + Guard l(x_contractMap); + for (ContractMap::const_iterator c = m_contractMap.cbegin(); c != m_contractMap.cend(); ++c) + result.insert(c.key(), QVariant::fromValue(c.value())); + return result; +} - std::string source = _code.toStdString(); - // run syntax highlighting first - // @todo combine this with compilation step - auto codeHighlighter = std::make_shared(); - codeHighlighter->processSource(source); +CompiledContract* CodeModel::contractByDocumentId(QString _documentId) const +{ + Guard l(x_contractMap); + for (ContractMap::const_iterator c = m_contractMap.cbegin(); c != m_contractMap.cend(); ++c) + if (c.value()->m_documentId == _documentId) + return c.value(); + return nullptr; +} + +CompiledContract const& CodeModel::contract(QString _name) const +{ + Guard l(x_contractMap); + CompiledContract* res = m_contractMap.value(_name); + if (res == nullptr) + BOOST_THROW_EXCEPTION(dev::Exception() << dev::errinfo_comment("Contract not found: " + _name.toStdString())); + return *res; +} - cs.addSource("configUser", R"(contract configUser{function configAddr()constant returns(address a){ return 0xf025d81196b72fba60a1d4dddad12eeb8360d828;}})"); +void CodeModel::releaseContracts() +{ + for (ContractMap::iterator c = m_contractMap.begin(); c != m_contractMap.end(); ++c) + c.value()->deleteLater(); + m_contractMap.clear(); +} + +void CodeModel::runCompilationJob(int _jobId) +{ + if (_jobId != m_backgroundJobId) + return; //obsolete job - // run compilation + ContractMap result; + solidity::CompilerStack cs(true); try { - cs.addSource("", source); + cs.addSource("configUser", R"(contract configUser{function configAddr()constant returns(address a){ return 0xf025d81196b72fba60a1d4dddad12eeb8360d828;}})"); + { + Guard l(x_pendingContracts); + for (auto const& c: m_pendingContracts) + cs.addSource(c.first.toStdString(), c.second.toStdString()); + } cs.compile(false); - codeHighlighter->processAST(cs.getAST()); - result.reset(new CompilationResult(cs)); - qDebug() << QString(QApplication::tr("compilation succeeded")); + + { + Guard pl(x_pendingContracts); + Guard l(x_contractMap); + for (std::string n: cs.getContractNames()) + { + if (c_predefinedContracts.count(n) != 0) + continue; + QString name = QString::fromStdString(n); + auto sourceIter = m_pendingContracts.find(name); + QString source = sourceIter != m_pendingContracts.end() ? sourceIter->second : QString(); + CompiledContract* contract = new CompiledContract(cs, name, source); + QQmlEngine::setObjectOwnership(contract, QQmlEngine::CppOwnership); + result[name] = contract; + CompiledContract* prevContract = m_contractMap.value(name); + if (prevContract != nullptr && prevContract->contractInterface() != result[name]->contractInterface()) + emit contractInterfaceChanged(name); + } + releaseContracts(); + m_contractMap.swap(result); + emit codeChanged(); + emit compilationComplete(); + } } catch (dev::Exception const& _exception) { std::ostringstream error; solidity::SourceReferenceFormatter::printExceptionInformation(error, _exception, "Error", cs); - result.reset(new CompilationResult(*m_result, QString::fromStdString(error.str()))); - codeHighlighter->processError(_exception); - qDebug() << QString(QApplication::tr("compilation failed:") + " " + result->compilerMessage()); + solidity::Location const* location = boost::get_error_info(_exception); + QString message = QString::fromStdString(error.str()); + CompiledContract* contract = nullptr; + if (location && location->sourceName.get() && (contract = contractByDocumentId(QString::fromStdString(*location->sourceName)))) + message = message.replace(QString::fromStdString(*location->sourceName), contract->contract()->name()); //substitute the location to match our contract names + compilationError(message); } - result->m_codeHighlighter = codeHighlighter; - result->m_codeHash = qHash(_code); - - emit compilationCompleteInternal(result.release()); -} - -void CodeModel::onCompilationComplete(CompilationResult* _newResult) -{ m_compiling = false; - bool contractChanged = m_result->contractInterface() != _newResult->contractInterface(); - m_result.reset(_newResult); - emit compilationComplete(); emit stateChanged(); - if (m_result->successful()) - { - emit codeChanged(); - if (contractChanged) - emit contractInterfaceChanged(); - } } bool CodeModel::hasContract() const { - return m_result->successful(); -} - -void CodeModel::updateFormatting(QTextDocument* _document) -{ - m_result->codeHighlighter()->updateFormatting(_document, *m_codeHighlighterSettings); + Guard l(x_contractMap); + return m_contractMap.size() != 0; } dev::bytes const& CodeModel::getStdContractCode(const QString& _contractName, const QString& _url) diff --git a/mix/CodeModel.h b/mix/CodeModel.h index 0262aa094..48dbbcd6c 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -27,7 +27,9 @@ #include #include #include +#include #include +#include class QTextDocument; @@ -56,59 +58,50 @@ public: BackgroundWorker(CodeModel* _model): QObject(), m_model(_model) {} public slots: - void queueCodeChange(int _jobId, QString const& _content); + void queueCodeChange(int _jobId); private: CodeModel* m_model; }; ///Compilation result model. Contains all the compiled contract data required by UI -class CompilationResult: public QObject +class CompiledContract: public QObject { Q_OBJECT Q_PROPERTY(QContractDefinition* contract READ contract) - Q_PROPERTY(QString compilerMessage READ compilerMessage CONSTANT) - Q_PROPERTY(bool successful READ successful CONSTANT) Q_PROPERTY(QString contractInterface READ contractInterface CONSTANT) Q_PROPERTY(QString codeHex READ codeHex CONSTANT) + Q_PROPERTY(QString documentId MEMBER m_documentId CONSTANT) public: - /// Empty compilation result constructor - CompilationResult(); /// Successful compilation result constructor - CompilationResult(solidity::CompilerStack const& _compiler); - /// Failed compilation result constructor - CompilationResult(CompilationResult const& _prev, QString const& _compilerMessage); + CompiledContract(solidity::CompilerStack const& _compiler, QString const& _contractName, QString const& _source); /// @returns contract definition for QML property - QContractDefinition* contract() { return m_contract.get(); } + QContractDefinition* contract() const { return m_contract.get(); } /// @returns contract definition - std::shared_ptr sharedContract() { return m_contract; } - /// Indicates if the compilation was successful - bool successful() const { return m_successful; } - /// @returns compiler error message in case of unsuccessful compilation - QString compilerMessage() const { return m_compilerMessage; } + std::shared_ptr sharedContract() const { return m_contract; } /// @returns contract bytecode dev::bytes const& bytes() const { return m_bytes; } /// @returns contract bytecode as hex string QString codeHex() const; /// @returns contract definition in JSON format QString contractInterface() const { return m_contractInterface; } - /// Get code highlighter - std::shared_ptr codeHighlighter() { return m_codeHighlighter; } private: - bool m_successful; - uint m_codeHash; + uint m_sourceHash; std::shared_ptr m_contract; QString m_compilerMessage; ///< @todo: use some structure here dev::bytes m_bytes; QString m_contractInterface; - std::shared_ptr m_codeHighlighter; + QString m_documentId; friend class CodeModel; }; -/// Background code compiler + +using ContractMap = QHash; + +/// Code compilation model. Compiles contracts in background an provides compiled contract data class CodeModel: public QObject { Q_OBJECT @@ -117,56 +110,59 @@ public: CodeModel(QObject* _parent); ~CodeModel(); - /// @returns latest compilation result - CompilationResult* code() { return m_result.get(); } - /// @returns latest compilation resul - CompilationResult const* code() const { return m_result.get(); } - - Q_PROPERTY(CompilationResult* code READ code NOTIFY codeChanged) + Q_PROPERTY(QVariantMap contracts READ contracts NOTIFY codeChanged) Q_PROPERTY(bool compiling READ isCompiling NOTIFY stateChanged) Q_PROPERTY(bool hasContract READ hasContract NOTIFY codeChanged) + /// @returns latest compilation results for contracts + QVariantMap contracts() const; /// @returns compilation status bool isCompiling() const { return m_compiling; } - /// @returns true if contract has at least one function + /// @returns true there is a contract which has at least one function bool hasContract() const; - /// Apply text document formatting. @todo Move this to editor module - void updateFormatting(QTextDocument* _document); /// Get contract code by url. Contract is compiled on first access and cached dev::bytes const& getStdContractCode(QString const& _contractName, QString const& _url); + /// Get contract by name + CompiledContract const& contract(QString _name) const; + /// Find a contract by document id + /// @returns CompiledContract object or null if not found + Q_INVOKABLE CompiledContract* contractByDocumentId(QString _documentId) const; signals: /// Emited on compilation state change void stateChanged(); /// Emitted on compilation complete void compilationComplete(); + /// Emitted on compilation error + void compilationError(QString _error); /// Internal signal used to transfer compilation job to background thread - void scheduleCompilationJob(int _jobId, QString const& _content); + void scheduleCompilationJob(int _jobId); /// Emitted if there are any changes in the code model void codeChanged(); /// Emitted if there are any changes in the contract interface - void contractInterfaceChanged(); - /// Emitted on compilation complete. Internal - void compilationCompleteInternal(CompilationResult* _newResult); - -private slots: - void onCompilationComplete(CompilationResult* _newResult); + void contractInterfaceChanged(QString _documentId); public slots: /// Update code model on source code change - void registerCodeChange(QString const& _code); + void registerCodeChange(QString const& _documentId, QString const& _code); + /// Reset code model for a new project + void reset(QVariantMap const& _documents); private: - void runCompilationJob(int _jobId, QString const& _content); + void runCompilationJob(int _jobId); void stop(); + void releaseContracts(); std::atomic m_compiling; - std::unique_ptr m_result; + mutable dev::Mutex x_contractMap; + ContractMap m_contractMap; std::unique_ptr m_codeHighlighterSettings; QThread m_backgroundThread; BackgroundWorker m_backgroundWorker; int m_backgroundJobId = 0; //protects from starting obsolete compilation job std::map m_compiledContracts; //by name + dev::Mutex x_pendingContracts; + std::map m_pendingContracts; //name to source friend class BackgroundWorker; }; diff --git a/mix/ContractCallDataEncoder.cpp b/mix/ContractCallDataEncoder.cpp index 19ece2a4d..e31f79e9f 100644 --- a/mix/ContractCallDataEncoder.cpp +++ b/mix/ContractCallDataEncoder.cpp @@ -56,7 +56,7 @@ QList ContractCallDataEncoder::decode(QList r; for (int k = 0; k <_returnParameters.length(); k++) { - QVariableDeclaration* dec = (QVariableDeclaration*)_returnParameters.at(k); + QVariableDeclaration* dec = static_cast(_returnParameters.at(k)); QVariableDefinition* def = nullptr; if (dec->type().contains("int")) def = new QIntType(dec, QString()); diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index b2a367929..a78bc017d 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -117,8 +117,8 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c unsigned dataIndex = 0; auto onOp = [&](uint64_t steps, Instruction inst, dev::bigint newMemSize, dev::bigint gasCost, void* voidVM, void const* voidExt) { - VM& vm = *(VM*)voidVM; - ExtVM const& ext = *(ExtVM const*)voidExt; + VM& vm = *static_cast(voidVM); + ExtVM const& ext = *static_cast(voidExt); if (lastCode == nullptr || lastCode != &ext.code) { auto const& iter = codeIndexes.find(&ext.code); @@ -463,6 +463,20 @@ eth::BlockInfo MixClient::uncle(h256 _blockHash, unsigned _i) const return BlockInfo(); } +unsigned MixClient::transactionCount(h256 _blockHash) const +{ + auto bl = bc().block(_blockHash); + RLP b(bl); + return b[1].itemCount(); +} + +unsigned MixClient::uncleCount(h256 _blockHash) const +{ + auto bl = bc().block(_blockHash); + RLP b(bl); + return b[2].itemCount(); +} + unsigned MixClient::number() const { return bc().number(); diff --git a/mix/MixClient.h b/mix/MixClient.h index 9ec5ff659..2fe92a7ae 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -71,6 +71,8 @@ public: eth::BlockDetails blockDetails(h256 _hash) const override; eth::Transaction transaction(h256 _blockHash, unsigned _i) const override; eth::BlockInfo uncle(h256 _blockHash, unsigned _i) const override; + unsigned transactionCount(h256 _blockHash) const override; + unsigned uncleCount(h256 _blockHash) const override; unsigned number() const override; eth::Transactions pending() const override; eth::StateDiff diff(unsigned _txi, h256 _block) const override; diff --git a/mix/QContractDefinition.cpp b/mix/QContractDefinition.cpp index 488e08ea3..eacaee2f9 100644 --- a/mix/QContractDefinition.cpp +++ b/mix/QContractDefinition.cpp @@ -42,7 +42,7 @@ QContractDefinition::QContractDefinition(dev::solidity::ContractDefinition const m_functions.append(new QFunctionDefinition(it.second));} -QFunctionDefinition* QContractDefinition::getFunction(dev::FixedHash<4> _hash) +QFunctionDefinition const* QContractDefinition::getFunction(dev::FixedHash<4> _hash) const { for (auto const& f: m_functions) if (f->hash() == _hash) diff --git a/mix/QContractDefinition.h b/mix/QContractDefinition.h index 22f913a70..4d586a239 100644 --- a/mix/QContractDefinition.h +++ b/mix/QContractDefinition.h @@ -47,7 +47,7 @@ public: QFunctionDefinition* constructor() const { return m_constructor; } QList const& functionsList() const { return m_functions; } /// Find function by hash, returns nullptr if not found - QFunctionDefinition* getFunction(dev::FixedHash<4> _hash); + QFunctionDefinition const* getFunction(dev::FixedHash<4> _hash) const; private: QList m_functions; QFunctionDefinition* m_constructor; diff --git a/mix/QVariableDefinition.h b/mix/QVariableDefinition.h index ae9bf9459..1825c2567 100644 --- a/mix/QVariableDefinition.h +++ b/mix/QVariableDefinition.h @@ -135,8 +135,8 @@ class QBoolType: public QVariableDefinition Q_OBJECT public: - QBoolType() {} - QBoolType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} + QBoolType(): m_boolValue(false) {} + QBoolType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value), m_boolValue(false) {} dev::bytes encodeValue() override; void decodeValue(dev::bytes const& _rawValue) override; /// @returns the boolean value for the current definition. diff --git a/mix/StatusPane.cpp b/mix/StatusPane.cpp index f74b8f22b..9022b7033 100644 --- a/mix/StatusPane.cpp +++ b/mix/StatusPane.cpp @@ -36,7 +36,6 @@ using namespace dev::mix; StatusPane::StatusPane(AppContext* _context): Extension(_context, ExtensionDisplayBehavior::HeaderView) { - connect(_context->codeModel(), &CodeModel::compilationComplete, this, &StatusPane::update); _context->appEngine()->rootContext()->setContextProperty("statusPane", this); } @@ -54,13 +53,3 @@ void StatusPane::start() const { } -CompilationResult* StatusPane::result() const -{ - return m_ctx->codeModel()->code(); -} - -void StatusPane::update() -{ - QObject* ctrl = m_view->findChild("statusPane", Qt::FindChildrenRecursively); - QMetaObject::invokeMethod(ctrl, "updateStatus"); -} diff --git a/mix/StatusPane.h b/mix/StatusPane.h index ee65252b5..28b5b449b 100644 --- a/mix/StatusPane.h +++ b/mix/StatusPane.h @@ -20,7 +20,6 @@ #pragma once #include "Extension.h" -#include "CodeModel.h" namespace dev { @@ -33,7 +32,6 @@ namespace mix class StatusPane: public Extension { Q_OBJECT - Q_PROPERTY(CompilationResult* result READ result CONSTANT) public: StatusPane(AppContext* _appContext); @@ -41,10 +39,8 @@ public: void start() const override; QString title() const override; QString contentUrl() const override; - CompilationResult* result() const; public slots: - void update(); }; } diff --git a/mix/main.cpp b/mix/main.cpp index d0a19cfb5..798520e39 100644 --- a/mix/main.cpp +++ b/mix/main.cpp @@ -36,6 +36,10 @@ int main(int _argc, char* _argv[]) //https://bugs.launchpad.net/ubuntu/+source/appmenu-qt5/+bug/1323853 putenv((char*)"QT_QPA_PLATFORMTHEME="); putenv((char*)"QSG_RENDER_LOOP=threaded"); +#endif +#if (defined(_WIN32) || defined(_WIN64)) + if (!getenv("OPENSSL_CONF")) + putenv((char*)"OPENSSL_CONF=c:\\"); #endif try { diff --git a/mix/qml/CodeEditorView.qml b/mix/qml/CodeEditorView.qml index 9c0b804d7..439c36199 100644 --- a/mix/qml/CodeEditorView.qml +++ b/mix/qml/CodeEditorView.qml @@ -43,7 +43,7 @@ Item { editor.onEditorTextChanged.connect(function() { documentEdit(document.documentId); if (document.isContract) - codeModel.registerCodeChange(editor.getText()); + codeModel.registerCodeChange(document.documentId, editor.getText()); }); editor.setText(data, document.syntaxMode); } diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index 1dd05574f..316ec86c7 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -25,7 +25,7 @@ Rectangle { function update(data, giveFocus) { - if (statusPane && statusPane.result.successful) + if (statusPane && codeModel.hasContract) { Debugger.init(data); debugScrollArea.visible = true; @@ -131,7 +131,14 @@ Rectangle { Layout.fillWidth: true Layout.minimumHeight: 60 height: 250 + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.leftMargin: machineStates.sideMargin + anchors.rightMargin: machineStates.sideMargin + anchors.topMargin: machineStates.sideMargin } + ScrollView { property int sideMargin: 10 diff --git a/mix/qml/DefaultLabel.qml b/mix/qml/DefaultLabel.qml index a1304e673..d8ef1faff 100644 --- a/mix/qml/DefaultLabel.qml +++ b/mix/qml/DefaultLabel.qml @@ -4,12 +4,6 @@ import "." Label { text: text - font.family: regularFont.name - font.pointSize: Style.generic.size.titlePointSize - SourceSansProLight - { - id: regularFont - } } diff --git a/mix/qml/DefaultTextField.qml b/mix/qml/DefaultTextField.qml index 6705273db..de306fa5e 100644 --- a/mix/qml/DefaultTextField.qml +++ b/mix/qml/DefaultTextField.qml @@ -3,11 +3,4 @@ import QtQuick.Controls 1.1 TextField { id: titleField - focus: true - font.family: regularFont.name - - SourceSansProRegular - { - id: regularFont; - } } diff --git a/mix/qml/Ether.qml b/mix/qml/Ether.qml index be41fced9..1a0f7ffe6 100644 --- a/mix/qml/Ether.qml +++ b/mix/qml/Ether.qml @@ -49,10 +49,6 @@ RowLayout { id: etherValueEdit; } - SourceSansProBold { - id: regularFont; - } - ComboBox { id: units @@ -87,15 +83,11 @@ RowLayout { ListElement { text: "Kwei"; } ListElement { text: "wei"; } } - style: ComboBoxStyle { - font: regularFont.name - } } Text { visible: displayFormattedValue id: formattedValue - font.family: regularFont.name } } diff --git a/mix/qml/MainContent.qml b/mix/qml/MainContent.qml index 6c6781878..15a7a638f 100644 --- a/mix/qml/MainContent.qml +++ b/mix/qml/MainContent.qml @@ -34,7 +34,7 @@ Rectangle { onCompilationComplete: { if (firstCompile) { firstCompile = false; - if (codeModel.code.successful && runOnProjectLoad) + if (runOnProjectLoad) startQuickDebugging(); } } diff --git a/mix/qml/ProjectList.qml b/mix/qml/ProjectList.qml index 925bb0bab..d4875220a 100644 --- a/mix/qml/ProjectList.qml +++ b/mix/qml/ProjectList.qml @@ -101,14 +101,19 @@ Item { Connections { target: codeModel onCompilationComplete: { - if (modelData === "Contracts") - { - var ctr = projectModel.listModel.get(0); - if (codeModel.code.contract.name !== ctr.name) - { - ctr.name = codeModel.code.contract.name; - projectModel.listModel.set(0, ctr); - sectionModel.set(0, ctr); + if (modelData === "Contracts") { + var ci = 0; + for (var si = 0; si < projectModel.listModel.count; si++) { + var document = projectModel.listModel.get(si); + if (document.isContract) { + var compiledDoc = codeModel.contractByDocumentId(document.documentId); + if (compiledDoc && compiledDoc.documentId === document.documentId && compiledDoc.contract.name !== document.name) { + document.name = compiledDoc.contract.name; + projectModel.listModel.set(si, document); + sectionModel.set(ci, document); + } + ci++; + } } } } diff --git a/mix/qml/ProjectModel.qml b/mix/qml/ProjectModel.qml index e74be7a9b..97dec227c 100644 --- a/mix/qml/ProjectModel.qml +++ b/mix/qml/ProjectModel.qml @@ -45,7 +45,7 @@ Item { function newHtmlFile() { ProjectModelCode.newHtmlFile(); } function newJsFile() { ProjectModelCode.newJsFile(); } function newCssFile() { ProjectModelCode.newCssFile(); } - //function newContract() { ProjectModelCode.newContract(); } + function newContract() { ProjectModelCode.newContract(); } function openDocument(documentId) { ProjectModelCode.openDocument(documentId); } function openNextDocument() { ProjectModelCode.openNextDocument(); } function openPrevDocument() { ProjectModelCode.openPrevDocument(); } diff --git a/mix/qml/StateDialog.qml b/mix/qml/StateDialog.qml index eeda2ae22..abb045497 100644 --- a/mix/qml/StateDialog.qml +++ b/mix/qml/StateDialog.qml @@ -12,7 +12,7 @@ Window { id: modalStateDialog modality: Qt.ApplicationModal - width: 450 + width: 520 height: 480 title: qsTr("Edit State") visible: false diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index c68a433f7..52b0d542d 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -22,12 +22,12 @@ Item { function fromPlainTransactionItem(t) { var r = { + contractId: t.contractId, functionId: t.functionId, url: t.url, value: QEtherHelper.createEther(t.value.value, t.value.unit), gas: QEtherHelper.createBigInt(t.gas.value), //t.gas,//QEtherHelper.createEther(t.gas.value, t.gas.unit), gasPrice: QEtherHelper.createEther(t.gasPrice.value, t.gasPrice.unit), - executeConstructor: t.executeConstructor, stdContract: t.stdContract, parameters: {} }; @@ -47,6 +47,10 @@ Item { varComponent = Qt.createComponent("qrc:/qml/QHashType.qml"); else if (type.indexOf("bool") !== -1) varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml"); + else { + console.log("Unknown parameter type: " + type); + continue; + } var param = varComponent.createObject(stateListModel); var dec = Qt.createComponent("qrc:/qml/QVariableDeclaration.qml"); @@ -78,12 +82,12 @@ Item { function toPlainTransactionItem(t) { var r = { + contractId: t.contractId, functionId: t.functionId, url: t.url, value: { value: t.value.value, unit: t.value.unit }, gas: { value: t.gas.value() }, gasPrice: { value: t.gasPrice.value, unit: t.gasPrice.unit }, - executeConstructor: t.executeConstructor, stdContract: t.stdContract, parameters: {} }; @@ -159,7 +163,6 @@ Item { value: QEtherHelper.createEther("100", QEther.Wei), gas: QEtherHelper.createBigInt("125000"), gasPrice: QEtherHelper.createEther("10000000000000", QEther.Wei), - executeConstructor: false, stdContract: false }; } @@ -178,16 +181,19 @@ Item { var contractTransaction = defaultTransactionItem(); var contractItem = contractLibrary.model.get(i); contractTransaction.url = contractItem.url; + contractTransaction.contractId = contractItem.name; contractTransaction.functionId = contractItem.name; contractTransaction.stdContract = true; item.transactions.push(contractTransaction); }; - //add constructor - var ctorTr = defaultTransactionItem(); - ctorTr.executeConstructor = true; - ctorTr.functionId = qsTr("Constructor"); - item.transactions.push(ctorTr); + //add constructors, //TODO: order by dependencies + for(var c in codeModel.contracts) { + var ctorTr = defaultTransactionItem(); + ctorTr.functionId = c; + ctorTr.contractId = c; + item.transactions.push(ctorTr); + } return item; } @@ -201,7 +207,7 @@ Item { } function debugDefaultState() { - if (defaultStateIndex >= 0) + if (defaultStateIndex >= 0 && defaultStateIndex < stateList.length) runState(defaultStateIndex); } @@ -219,6 +225,9 @@ Item { defaultStateIndex = 0; defaultStateChanged(); } + else if (defaultStateIndex > index) + defaultStateIndex--; + save(); } diff --git a/mix/qml/StatusPane.qml b/mix/qml/StatusPane.qml index ddadb9953..6a8a0093d 100644 --- a/mix/qml/StatusPane.qml +++ b/mix/qml/StatusPane.qml @@ -8,9 +8,9 @@ Rectangle { id: statusHeader objectName: "statusPane" - function updateStatus() + function updateStatus(message) { - if (statusPane.result.successful) + if (!message) { status.state = ""; status.text = qsTr("Compile without errors."); @@ -20,12 +20,12 @@ Rectangle { else { status.state = "error"; - var errorInfo = ErrorLocationFormater.extractErrorInfo(statusPane.result.compilerMessage, true); + var errorInfo = ErrorLocationFormater.extractErrorInfo(message, true); status.text = errorInfo.errorLocation + " " + errorInfo.errorDetail; logslink.visible = true; debugImg.state = ""; } - debugRunActionIcon.enabled = statusPane.result.successful; + debugRunActionIcon.enabled = codeModel.hasContract; } function infoMessage(text) @@ -35,7 +35,6 @@ Rectangle { logslink.visible = false; } - Connections { target:clientModel onRunStarted: infoMessage(qsTr("Running transactions...")); @@ -49,6 +48,11 @@ Rectangle { onDeploymentError: infoMessage(error); onDeploymentComplete: infoMessage(qsTr("Deployment complete")); } + Connections { + target: codeModel + onCompilationComplete: updateStatus(); + onCompilationError: updateStatus(_error); + } color: "transparent" anchors.fill: parent diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index a38886354..e5a8bc746 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -10,7 +10,7 @@ import "." Window { id: modalTransactionDialog modality: Qt.ApplicationModal - width: 450 + width: 520 height: (paramsModel.count > 0 ? 500 : 300) visible: false color: StateDialogStyle.generic.backgroundColor @@ -20,9 +20,9 @@ Window { property alias gas: gasValueEdit.gasValue; property alias gasPrice: gasPriceField.value; property alias transactionValue: valueField.value; + property string contractId: contractComboBox.currentValue(); property alias functionId: functionComboBox.currentText; property var itemParams; - property bool isConstructorTransaction; property bool useTransactionDefaultValue: false property var qType; @@ -39,32 +39,47 @@ Window { gasValueEdit.gasValue = item.gas; gasPriceField.value = item.gasPrice; valueField.value = item.value; + var contractId = item.contractId; var functionId = item.functionId; - isConstructorTransaction = item.executeConstructor; - rowFunction.visible = !item.executeConstructor; + rowFunction.visible = true; itemParams = item.parameters !== undefined ? item.parameters : {}; - functionsModel.clear(); + + contractsModel.clear(); + var contractIndex = -1; + var contracts = codeModel.contracts; + for (var c in contracts) { + contractsModel.append({ cid: c, text: contracts[c].contract.name }); + if (contracts[c].contract.name === contractId) + contractIndex = contractsModel.count - 1; + } + + if (contractIndex == -1 && contractsModel.count > 0) + contractIndex = 0; //@todo suggest unused contract + contractComboBox.currentIndex = contractIndex; + + loadFunctions(contractComboBox.currentValue()); + var functionIndex = -1; - var functions = codeModel.code.contract.functions; - for (var f = 0; f < functions.length; f++) { - functionsModel.append({ text: functions[f].name }); - if (functions[f].name === item.functionId) + for (var f = 0; f < functionsModel.count; f++) + if (functionsModel.get(f).text === item.functionId) functionIndex = f; - } if (functionIndex == -1 && functionsModel.count > 0) functionIndex = 0; //@todo suggest unused function functionComboBox.currentIndex = functionIndex; + paramsModel.clear(); - if (!item.executeConstructor) + if (functionId !== contractComboBox.currentValue()) loadParameters(); - else - { - var parameters = codeModel.code.contract.constructor.parameters; - for (var p = 0; p < parameters.length; p++) - loadParameter(parameters[p]); + else { + var contract = codeModel.contracts[contractId]; + if (contract) { + var parameters = contract.contract.constructor.parameters; + for (var p = 0; p < parameters.length; p++) + loadParameter(parameters[p]); + } } modalTransactionDialog.setX((Screen.width - width) / 2); modalTransactionDialog.setY((Screen.height - height) / 2); @@ -73,6 +88,21 @@ Window { valueField.focus = true; } + function loadFunctions(contractId) + { + functionsModel.clear(); + var contract = codeModel.contracts[contractId]; + if (contract) { + var functions = codeModel.contracts[contractId].contract.functions; + for (var f = 0; f < functions.length; f++) { + functionsModel.append({ text: functions[f].name }); + } + } + //append constructor + functionsModel.append({ text: contractId }); + + } + function loadParameter(parameter) { var type = parameter.type; @@ -104,10 +134,15 @@ Window { if (!paramsModel) return; if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) { - var func = codeModel.code.contract.functions[functionComboBox.currentIndex]; - var parameters = func.parameters; - for (var p = 0; p < parameters.length; p++) - loadParameter(parameters[p]); + var contract = codeModel.contracts[contractComboBox.currentValue()]; + if (contract) { + var func = contract.contract.functions[functionComboBox.currentIndex]; + if (func) { + var parameters = func.parameters; + for (var p = 0; p < parameters.length; p++) + loadParameter(parameters[p]); + } + } } } @@ -140,24 +175,21 @@ Window { if (!useTransactionDefaultValue) { item = { + contractId: transactionDialog.contractId, functionId: transactionDialog.functionId, gas: transactionDialog.gas, gasPrice: transactionDialog.gasPrice, value: transactionDialog.transactionValue, parameters: {}, - executeConstructor: isConstructorTransaction }; } else { item = TransactionHelper.defaultTransaction(); + item.contractId = transactionDialog.contractId; item.functionId = transactionDialog.functionId; - item.executeConstructor = isConstructorTransaction; } - if (isConstructorTransaction) - item.functionId = qsTr("Constructor"); - var orderedQType = []; for (var p = 0; p < transactionDialog.transactionParams.count; p++) { var parameter = transactionDialog.transactionParams.get(p); @@ -174,15 +206,37 @@ Window { anchors.fill: parent anchors.margins: 10 - SourceSansProLight - { - id: lightFont - } - ColumnLayout { id: dialogContent anchors.top: parent.top spacing: 10 + RowLayout + { + id: rowContract + Layout.fillWidth: true + height: 150 + DefaultLabel { + Layout.preferredWidth: 75 + text: qsTr("Contract") + } + ComboBox { + id: contractComboBox + function currentValue() { + return (currentIndex >=0 && currentIndex < contractsModel.count) ? contractsModel.get(currentIndex).cid : ""; + } + Layout.preferredWidth: 350 + currentIndex: -1 + textRole: "text" + editable: false + model: ListModel { + id: contractsModel + } + onCurrentIndexChanged: { + loadFunctions(currentValue()); + } + } + } + RowLayout { id: rowFunction @@ -204,9 +258,6 @@ Window { onCurrentIndexChanged: { loadParameters(); } - style: ComboBoxStyle { - font: lightFont.name - } } } diff --git a/mix/qml/WebPreview.qml b/mix/qml/WebPreview.qml index 88b992b54..0d0d70d31 100644 --- a/mix/qml/WebPreview.qml +++ b/mix/qml/WebPreview.qml @@ -24,12 +24,23 @@ Item { } function reload() { - updateContract(); - webView.runJavaScript("reloadPage()"); + if (initialized) { + updateContract(); + webView.runJavaScript("reloadPage()"); + } } function updateContract() { - webView.runJavaScript("updateContract(\"" + codeModel.code.contract.name + "\", \"" + clientModel.contractAddress + "\", " + codeModel.code.contractInterface + ")"); + var contracts = {}; + for (var c in codeModel.contracts) { + var contract = codeModel.contracts[c]; + contracts[c] = { + name: contract.contract.name, + address: clientModel.contractAddresses[contract.contract.name], + interface: JSON.parse(contract.contractInterface), + }; + } + webView.runJavaScript("updateContracts(" + JSON.stringify(contracts) + ")"); } function reloadOnSave() { @@ -62,7 +73,6 @@ Item { Connections { target: clientModel - onContractAddressChanged: reload(); onRunComplete: reload(); } @@ -162,11 +172,6 @@ Item { spacing: 0 Rectangle { - SourceSansProLight - { - id: regularFont - } - anchors.leftMargin: 4 color: WebPreviewStyle.general.headerBackgroundColor Layout.preferredWidth: parent.width @@ -188,9 +193,7 @@ Item { currentIndex: -1 onCurrentIndexChanged: changePage() anchors.verticalCenter: parent.verticalCenter - style: ComboBoxStyle { - font: regularFont.name - } + height: 21 } Action { @@ -205,12 +208,13 @@ Item { iconSource: "qrc:/qml/img/available_updates.png" action: buttonReloadAction anchors.verticalCenter: parent.verticalCenter - width: 26 - height: 26 + width: 21 + height: 21 } CheckBox { id: autoReloadOnSave checked: true + height: 21 anchors.verticalCenter: parent.verticalCenter style: CheckBoxStyle { label: DefaultLabel { diff --git a/mix/qml/html/WebContainer.html b/mix/qml/html/WebContainer.html index 09a8734d5..26cac5103 100644 --- a/mix/qml/html/WebContainer.html +++ b/mix/qml/html/WebContainer.html @@ -15,16 +15,18 @@ reloadPage = function() { preview.contentWindow.location.reload(); }; -updateContract = function(name, address, contractFace) { +updateContracts = function(contracts) { if (window.web3) { window.web3.provider.polls = []; - var contract = window.web3.eth.contract(address, contractFace); window.contracts = {}; - window.contracts[name] = { - address: address, - interface: contractFace, - contract: contract, - }; + for (var c in contracts) { + var contract = window.web3.eth.contract(contracts[c].address, contracts[c].interface); + window.contracts[c] = { + address: c.address, + interface: c.interface, + contract: contract, + }; + } } }; diff --git a/mix/qml/js/ProjectModel.js b/mix/qml/js/ProjectModel.js index be6c07c5b..5a7bf4332 100644 --- a/mix/qml/js/ProjectModel.js +++ b/mix/qml/js/ProjectModel.js @@ -20,6 +20,9 @@ * Ethereum IDE client. */ +var htmlTemplate = "\n\n\n\n\n\n\n"; +var contractTemplate = "contract Contract {\n}\n"; + function saveAll() { saveProject(); } @@ -76,6 +79,16 @@ function loadProject(path) { projectSettings.lastProjectPath = path; projectLoading(projectData); projectLoaded() + + //TODO: move this to codemodel + var contractSources = {}; + for (var d = 0; d < listModel.count; d++) { + var doc = listModel.get(d); + if (doc.isContract) + contractSources[doc.documentId] = fileIo.readFile(doc.path); + } + codeModel.reset(contractSources); + } function addFile(fileName) { @@ -92,7 +105,7 @@ function addFile(fileName) { contract: false, path: p, fileName: fileName, - name: isContract ? "Contract" : fileName, + name: fileName, documentId: fileName, syntaxMode: syntaxMode, isText: isContract || isHtml || isCss || isJs, @@ -150,7 +163,7 @@ function openPrevDocument() { } function doCloseProject() { - console.log("closing project"); + console.log("Closing project"); projectListModel.clear(); projectPath = ""; currentDocumentId = ""; @@ -167,14 +180,14 @@ function doCreateProject(title, path) { var projectFile = dirPath + projectFileName; var indexFile = "index.html"; - var contractsFile = "contracts.sol"; + var contractsFile = "contract.sol"; var projectData = { title: title, files: [ contractsFile, indexFile ] }; //TODO: copy from template - fileIo.writeFile(dirPath + indexFile, "\n\n\n\n\n\n\n"); - fileIo.writeFile(dirPath + contractsFile, "contract Contract {\n}\n"); + fileIo.writeFile(dirPath + indexFile, htmlTemplate); + fileIo.writeFile(dirPath + contractsFile, contractTemplate); newProject(projectData); var json = JSON.stringify(projectData, null, "\t"); fileIo.writeFile(projectFile, json); @@ -222,7 +235,7 @@ function removeDocument(documentId) { } function newHtmlFile() { - createAndAddFile("page", "html", "\n"); + createAndAddFile("page", "html", htmlTemplate); } function newCssFile() { @@ -233,6 +246,11 @@ function newJsFile() { createAndAddFile("script", "js", "function foo() {\n}\n"); } +function newContract() { + createAndAddFile("contract", "sol", contractTemplate); +} + + function createAndAddFile(name, extension, content) { var fileName = generateFileName(name, extension); var filePath = projectPath + fileName; @@ -267,15 +285,21 @@ function deployProject(force) { var jsonRpcUrl = "http://localhost:8080"; console.log("Deploying " + deploymentId + " to " + jsonRpcUrl); deploymentStarted(); - var code = codeModel.codeHex - var rpcRequest = JSON.stringify({ - jsonrpc: "2.0", - method: "eth_transact", - params: [ { - "code": code - } ], - id: jsonRpcRequestId++ - }); + + var requests = []; + var requestNames = []; + for (var c in codeModel.contracts) { //TODO: order based on dependencies + var code = codeModel.contracts[c].codeHex; + requests.push({ + jsonrpc: "2.0", + method: "eth_transact", + params: [ { "code": code } ], + id: jsonRpcRequestId++ + }); + requestNames.push(c); + } + + var rpcRequest = JSON.stringify(requests);; var httpRequest = new XMLHttpRequest() httpRequest.open("POST", jsonRpcUrl, true); httpRequest.setRequestHeader("Content-type", "application/json"); @@ -285,9 +309,12 @@ function deployProject(force) { if (httpRequest.readyState === XMLHttpRequest.DONE) { if (httpRequest.status === 200) { var rpcResponse = JSON.parse(httpRequest.responseText); - var address = rpcResponse.result; - console.log("Created contract, address: " + address); - finalizeDeployment(deploymentId, address); + if (rpcResponse.length === requestNames.length) { + var contractAddresses = {}; + for (var r = 0; r < rpcResponse.lenght; r++) + contractAddresses[requestNames[r]] = rpcResponse.result; + finalizeDeployment(deploymentId, contractAddresses); + } } else { var errorText = qsTr("Deployment error: RPC server HTTP status ") + httpRequest.status; console.log(errorText); @@ -298,7 +325,7 @@ function deployProject(force) { httpRequest.send(rpcRequest); } -function finalizeDeployment(deploymentId, address) { +function finalizeDeployment(deploymentId, addresses) { //create a dir for frontend files and copy them var deploymentDir = projectPath + deploymentId + "/"; fileIo.makeDir(deploymentDir); @@ -326,16 +353,18 @@ function finalizeDeployment(deploymentId, address) { fileIo.copyFile(doc.path, deploymentDir + doc.fileName); } //write deployment js - var contractAccessor = "contracts[\"" + codeModel.code.contract.name + "\"]"; var deploymentJs = "// Autogenerated by Mix\n" + "web3 = require(\"web3\");\n" + - "contracts = {};\n" + - contractAccessor + " = {\n" + - "\tinterface: " + codeModel.code.contractInterface + ",\n" + - "\taddress: \"" + address + "\"\n" + + "contracts = {};\n"; + for (var c in codeModel.contracts) { + var contractAccessor = "contracts[\"" + codeModel.contracts[c].contract.name + "\"]"; + deploymentJs += contractAccessor + " = {\n" + + "\tinterface: " + codeModel.contracts[c].contractInterface + ",\n" + + "\taddress: \"" + addresses[c] + "\"\n" + "};\n" + contractAccessor + ".contract = web3.eth.contract(" + contractAccessor + ".address, " + contractAccessor + ".interface);\n"; + } fileIo.writeFile(deploymentDir + "deployment.js", deploymentJs); //copy scripts fileIo.copyFile("qrc:///js/bignumber.min.js", deploymentDir + "bignumber.min.js"); diff --git a/mix/qml/js/TransactionHelper.js b/mix/qml/js/TransactionHelper.js index 87dd74beb..62399161e 100644 --- a/mix/qml/js/TransactionHelper.js +++ b/mix/qml/js/TransactionHelper.js @@ -7,7 +7,6 @@ function defaultTransaction() functionId: "", gas: createBigInt("125000"), gasPrice: createEther("100000", QEther.Wei), - executeConstructor: false, parameters: {} }; } diff --git a/mix/qml/main.qml b/mix/qml/main.qml index 71d8c24bf..c9e8c8225 100644 --- a/mix/qml/main.qml +++ b/mix/qml/main.qml @@ -30,7 +30,7 @@ ApplicationWindow { MenuItem { action: addNewHtmlFileAction } MenuItem { action: addNewCssFileAction } MenuSeparator {} - //MenuItem { action: addNewContractAction } + MenuItem { action: addNewContractAction } MenuItem { action: closeProjectAction } MenuSeparator {} MenuItem { action: exitAppAction } @@ -95,7 +95,7 @@ ApplicationWindow { text: qsTr("Mine") shortcut: "Ctrl+M" onTriggered: clientModel.mine(); - enabled: codeModel.hasContract && !clientModel.running &&!clientModel.mining + enabled: codeModel.hasContract && !clientModel.running && !clientModel.mining } StateList { diff --git a/neth/CMakeLists.txt b/neth/CMakeLists.txt index 4db3d2cf4..caf7d2f97 100644 --- a/neth/CMakeLists.txt +++ b/neth/CMakeLists.txt @@ -2,9 +2,9 @@ cmake_policy(SET CMP0015 NEW) aux_source_directory(. SRC_LIST) +include_directories(BEFORE ..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) include_directories(${LEVELDB_INCLUDE_DIRS}) -include_directories(..) set(EXECUTABLE neth) diff --git a/sc/CMakeLists.txt b/sc/CMakeLists.txt index ee638bb52..313a47fab 100644 --- a/sc/CMakeLists.txt +++ b/sc/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_policy(SET CMP0015 NEW) aux_source_directory(. SRC_LIST) -include_directories(..) +include_directories(BEFORE ..) set(EXECUTABLE sc) diff --git a/solc/CMakeLists.txt b/solc/CMakeLists.txt index 747effad0..d3a39dbc8 100644 --- a/solc/CMakeLists.txt +++ b/solc/CMakeLists.txt @@ -3,8 +3,8 @@ set(CMAKE_AUTOMOC OFF) aux_source_directory(. SRC_LIST) -include_directories(..) include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) +include_directories(BEFORE ..) include_directories(${Boost_INCLUDE_DIRS}) set(EXECUTABLE solc) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6ba07f280..bc14918b8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,8 +4,8 @@ aux_source_directory(. SRC_LIST) list(REMOVE_ITEM SRC_LIST "./createRandomTest.cpp") list(REMOVE_ITEM SRC_LIST "./checkRandomTest.cpp") -include_directories(..) include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS}) +include_directories(BEFORE ..) include_directories(${Boost_INCLUDE_DIRS}) include_directories(${CRYPTOPP_INCLUDE_DIRS}) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) diff --git a/test/ManyFunctions.sol b/test/ManyFunctions.sol new file mode 100644 index 000000000..691d98f46 --- /dev/null +++ b/test/ManyFunctions.sol @@ -0,0 +1,1513 @@ + +// Based on input param calls ~100 functions from ~200, random algorithm is really bad. +contract ManyFunctions { + + function start(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**78) + return left1(r); + return right1(r); + } + + function finish(uint seed) returns (uint) { + return seed; + } + + function nextRand(uint seed) returns (uint) { + var a = 39948330534945941795786356397633709378407037920056054402537049186942880579585; + return a * seed + 1; + } + + function right100(uint seed) returns (uint) { + return finish(seed); + } + + function left100(uint seed) returns (uint) { + return finish(nextRand(seed)); + } + + function right1(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**79) + return right2(r); + return left2(r); + } + + function left1(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**79) + return left2(r); + return right2(r); + } + + + function right2(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**80) + return right3(r); + return left3(r); + } + + function left2(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**80) + return left3(r); + return right3(r); + } + + + function right3(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**81) + return right4(r); + return left4(r); + } + + function left3(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**81) + return left4(r); + return right4(r); + } + + + function right4(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**82) + return right5(r); + return left5(r); + } + + function left4(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**82) + return left5(r); + return right5(r); + } + + + function right5(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**83) + return right6(r); + return left6(r); + } + + function left5(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**83) + return left6(r); + return right6(r); + } + + + function right6(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**84) + return right7(r); + return left7(r); + } + + function left6(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**84) + return left7(r); + return right7(r); + } + + + function right7(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**85) + return right8(r); + return left8(r); + } + + function left7(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**85) + return left8(r); + return right8(r); + } + + + function right8(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**86) + return right9(r); + return left9(r); + } + + function left8(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**86) + return left9(r); + return right9(r); + } + + + function right9(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**87) + return right10(r); + return left10(r); + } + + function left9(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**87) + return left10(r); + return right10(r); + } + + + function right10(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**88) + return right11(r); + return left11(r); + } + + function left10(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**88) + return left11(r); + return right11(r); + } + + + function right11(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**89) + return right12(r); + return left12(r); + } + + function left11(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**89) + return left12(r); + return right12(r); + } + + + function right12(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**90) + return right13(r); + return left13(r); + } + + function left12(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**90) + return left13(r); + return right13(r); + } + + + function right13(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**91) + return right14(r); + return left14(r); + } + + function left13(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**91) + return left14(r); + return right14(r); + } + + + function right14(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**92) + return right15(r); + return left15(r); + } + + function left14(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**92) + return left15(r); + return right15(r); + } + + + function right15(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**93) + return right16(r); + return left16(r); + } + + function left15(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**93) + return left16(r); + return right16(r); + } + + + function right16(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**94) + return right17(r); + return left17(r); + } + + function left16(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**94) + return left17(r); + return right17(r); + } + + + function right17(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**95) + return right18(r); + return left18(r); + } + + function left17(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**95) + return left18(r); + return right18(r); + } + + + function right18(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**96) + return right19(r); + return left19(r); + } + + function left18(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**96) + return left19(r); + return right19(r); + } + + + function right19(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**97) + return right20(r); + return left20(r); + } + + function left19(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**97) + return left20(r); + return right20(r); + } + + + function right20(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**98) + return right21(r); + return left21(r); + } + + function left20(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**98) + return left21(r); + return right21(r); + } + + + function right21(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**99) + return right22(r); + return left22(r); + } + + function left21(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**99) + return left22(r); + return right22(r); + } + + + function right22(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**100) + return right23(r); + return left23(r); + } + + function left22(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**100) + return left23(r); + return right23(r); + } + + + function right23(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**101) + return right24(r); + return left24(r); + } + + function left23(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**101) + return left24(r); + return right24(r); + } + + + function right24(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**102) + return right25(r); + return left25(r); + } + + function left24(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**102) + return left25(r); + return right25(r); + } + + + function right25(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**103) + return right26(r); + return left26(r); + } + + function left25(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**103) + return left26(r); + return right26(r); + } + + + function right26(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**104) + return right27(r); + return left27(r); + } + + function left26(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**104) + return left27(r); + return right27(r); + } + + + function right27(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**105) + return right28(r); + return left28(r); + } + + function left27(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**105) + return left28(r); + return right28(r); + } + + + function right28(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**106) + return right29(r); + return left29(r); + } + + function left28(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**106) + return left29(r); + return right29(r); + } + + + function right29(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**107) + return right30(r); + return left30(r); + } + + function left29(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**107) + return left30(r); + return right30(r); + } + + + function right30(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**108) + return right31(r); + return left31(r); + } + + function left30(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**108) + return left31(r); + return right31(r); + } + + + function right31(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**109) + return right32(r); + return left32(r); + } + + function left31(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**109) + return left32(r); + return right32(r); + } + + + function right32(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**110) + return right33(r); + return left33(r); + } + + function left32(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**110) + return left33(r); + return right33(r); + } + + + function right33(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**111) + return right34(r); + return left34(r); + } + + function left33(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**111) + return left34(r); + return right34(r); + } + + + function right34(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**112) + return right35(r); + return left35(r); + } + + function left34(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**112) + return left35(r); + return right35(r); + } + + + function right35(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**113) + return right36(r); + return left36(r); + } + + function left35(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**113) + return left36(r); + return right36(r); + } + + + function right36(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**114) + return right37(r); + return left37(r); + } + + function left36(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**114) + return left37(r); + return right37(r); + } + + + function right37(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**115) + return right38(r); + return left38(r); + } + + function left37(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**115) + return left38(r); + return right38(r); + } + + + function right38(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**116) + return right39(r); + return left39(r); + } + + function left38(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**116) + return left39(r); + return right39(r); + } + + + function right39(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**117) + return right40(r); + return left40(r); + } + + function left39(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**117) + return left40(r); + return right40(r); + } + + + function right40(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**118) + return right41(r); + return left41(r); + } + + function left40(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**118) + return left41(r); + return right41(r); + } + + + function right41(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**119) + return right42(r); + return left42(r); + } + + function left41(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**119) + return left42(r); + return right42(r); + } + + + function right42(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**120) + return right43(r); + return left43(r); + } + + function left42(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**120) + return left43(r); + return right43(r); + } + + + function right43(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**121) + return right44(r); + return left44(r); + } + + function left43(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**121) + return left44(r); + return right44(r); + } + + + function right44(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**122) + return right45(r); + return left45(r); + } + + function left44(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**122) + return left45(r); + return right45(r); + } + + + function right45(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**123) + return right46(r); + return left46(r); + } + + function left45(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**123) + return left46(r); + return right46(r); + } + + + function right46(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**124) + return right47(r); + return left47(r); + } + + function left46(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**124) + return left47(r); + return right47(r); + } + + + function right47(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**125) + return right48(r); + return left48(r); + } + + function left47(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**125) + return left48(r); + return right48(r); + } + + + function right48(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**126) + return right49(r); + return left49(r); + } + + function left48(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**126) + return left49(r); + return right49(r); + } + + + function right49(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**127) + return right50(r); + return left50(r); + } + + function left49(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**127) + return left50(r); + return right50(r); + } + + + function right50(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**128) + return right51(r); + return left51(r); + } + + function left50(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**128) + return left51(r); + return right51(r); + } + + + function right51(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**129) + return right52(r); + return left52(r); + } + + function left51(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**129) + return left52(r); + return right52(r); + } + + + function right52(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**130) + return right53(r); + return left53(r); + } + + function left52(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**130) + return left53(r); + return right53(r); + } + + + function right53(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**131) + return right54(r); + return left54(r); + } + + function left53(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**131) + return left54(r); + return right54(r); + } + + + function right54(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**132) + return right55(r); + return left55(r); + } + + function left54(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**132) + return left55(r); + return right55(r); + } + + + function right55(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**133) + return right56(r); + return left56(r); + } + + function left55(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**133) + return left56(r); + return right56(r); + } + + + function right56(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**134) + return right57(r); + return left57(r); + } + + function left56(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**134) + return left57(r); + return right57(r); + } + + + function right57(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**135) + return right58(r); + return left58(r); + } + + function left57(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**135) + return left58(r); + return right58(r); + } + + + function right58(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**136) + return right59(r); + return left59(r); + } + + function left58(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**136) + return left59(r); + return right59(r); + } + + + function right59(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**137) + return right60(r); + return left60(r); + } + + function left59(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**137) + return left60(r); + return right60(r); + } + + + function right60(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**138) + return right61(r); + return left61(r); + } + + function left60(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**138) + return left61(r); + return right61(r); + } + + + function right61(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**139) + return right62(r); + return left62(r); + } + + function left61(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**139) + return left62(r); + return right62(r); + } + + + function right62(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**140) + return right63(r); + return left63(r); + } + + function left62(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**140) + return left63(r); + return right63(r); + } + + + function right63(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**141) + return right64(r); + return left64(r); + } + + function left63(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**141) + return left64(r); + return right64(r); + } + + + function right64(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**142) + return right65(r); + return left65(r); + } + + function left64(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**142) + return left65(r); + return right65(r); + } + + + function right65(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**143) + return right66(r); + return left66(r); + } + + function left65(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**143) + return left66(r); + return right66(r); + } + + + function right66(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**144) + return right67(r); + return left67(r); + } + + function left66(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**144) + return left67(r); + return right67(r); + } + + + function right67(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**145) + return right68(r); + return left68(r); + } + + function left67(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**145) + return left68(r); + return right68(r); + } + + + function right68(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**146) + return right69(r); + return left69(r); + } + + function left68(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**146) + return left69(r); + return right69(r); + } + + + function right69(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**147) + return right70(r); + return left70(r); + } + + function left69(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**147) + return left70(r); + return right70(r); + } + + + function right70(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**148) + return right71(r); + return left71(r); + } + + function left70(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**148) + return left71(r); + return right71(r); + } + + + function right71(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**149) + return right72(r); + return left72(r); + } + + function left71(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**149) + return left72(r); + return right72(r); + } + + + function right72(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**150) + return right73(r); + return left73(r); + } + + function left72(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**150) + return left73(r); + return right73(r); + } + + + function right73(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**151) + return right74(r); + return left74(r); + } + + function left73(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**151) + return left74(r); + return right74(r); + } + + + function right74(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**152) + return right75(r); + return left75(r); + } + + function left74(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**152) + return left75(r); + return right75(r); + } + + + function right75(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**153) + return right76(r); + return left76(r); + } + + function left75(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**153) + return left76(r); + return right76(r); + } + + + function right76(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**154) + return right77(r); + return left77(r); + } + + function left76(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**154) + return left77(r); + return right77(r); + } + + + function right77(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**155) + return right78(r); + return left78(r); + } + + function left77(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**155) + return left78(r); + return right78(r); + } + + + function right78(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**156) + return right79(r); + return left79(r); + } + + function left78(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**156) + return left79(r); + return right79(r); + } + + + function right79(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**157) + return right80(r); + return left80(r); + } + + function left79(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**157) + return left80(r); + return right80(r); + } + + + function right80(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**158) + return right81(r); + return left81(r); + } + + function left80(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**158) + return left81(r); + return right81(r); + } + + + function right81(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**159) + return right82(r); + return left82(r); + } + + function left81(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**159) + return left82(r); + return right82(r); + } + + + function right82(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**160) + return right83(r); + return left83(r); + } + + function left82(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**160) + return left83(r); + return right83(r); + } + + + function right83(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**161) + return right84(r); + return left84(r); + } + + function left83(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**161) + return left84(r); + return right84(r); + } + + + function right84(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**162) + return right85(r); + return left85(r); + } + + function left84(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**162) + return left85(r); + return right85(r); + } + + + function right85(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**163) + return right86(r); + return left86(r); + } + + function left85(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**163) + return left86(r); + return right86(r); + } + + + function right86(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**164) + return right87(r); + return left87(r); + } + + function left86(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**164) + return left87(r); + return right87(r); + } + + + function right87(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**165) + return right88(r); + return left88(r); + } + + function left87(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**165) + return left88(r); + return right88(r); + } + + + function right88(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**166) + return right89(r); + return left89(r); + } + + function left88(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**166) + return left89(r); + return right89(r); + } + + + function right89(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**167) + return right90(r); + return left90(r); + } + + function left89(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**167) + return left90(r); + return right90(r); + } + + + function right90(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**168) + return right91(r); + return left91(r); + } + + function left90(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**168) + return left91(r); + return right91(r); + } + + + function right91(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**169) + return right92(r); + return left92(r); + } + + function left91(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**169) + return left92(r); + return right92(r); + } + + + function right92(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**170) + return right93(r); + return left93(r); + } + + function left92(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**170) + return left93(r); + return right93(r); + } + + + function right93(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**171) + return right94(r); + return left94(r); + } + + function left93(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**171) + return left94(r); + return right94(r); + } + + + function right94(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**172) + return right95(r); + return left95(r); + } + + function left94(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**172) + return left95(r); + return right95(r); + } + + + function right95(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**173) + return right96(r); + return left96(r); + } + + function left95(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**173) + return left96(r); + return right96(r); + } + + + function right96(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**174) + return right97(r); + return left97(r); + } + + function left96(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**174) + return left97(r); + return right97(r); + } + + + function right97(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**175) + return right98(r); + return left98(r); + } + + function left97(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**175) + return left98(r); + return right98(r); + } + + + function right98(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**176) + return right99(r); + return left99(r); + } + + function left98(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**176) + return left99(r); + return right99(r); + } + + + function right99(uint seed) returns (uint) { + var r = nextRand(seed); + if (r >= 2**177) + return right100(r); + return left100(r); + } + + function left99(uint seed) returns (uint) { + var r = nextRand(nextRand(seed)); + if (r >= 2**177) + return left100(r); + return right100(r); + } + +} \ No newline at end of file diff --git a/test/ManyFunctionsGenerator.py b/test/ManyFunctionsGenerator.py new file mode 100644 index 000000000..b4f36af0e --- /dev/null +++ b/test/ManyFunctionsGenerator.py @@ -0,0 +1,24 @@ + +n = 100 + +splitNumBegin = 128 - (n / 2) +i = 1 + +template = """ + function right{0}(uint seed) returns (uint) {{ + var r = nextRand(seed); + if (r >= 2**{2}) + return right{1}(r); + return left{1}(r); + }} + + function left{0}(uint seed) returns (uint) {{ + var r = nextRand(nextRand(seed)); + if (r >= 2**{2}) + return left{1}(r); + return right{1}(r); + }} +""" + +for i in range(1, n): + print template.format(i, i + 1, i + splitNumBegin) \ No newline at end of file diff --git a/test/SolidityCompiler.cpp b/test/SolidityCompiler.cpp index 17d9a7c07..1369b038f 100644 --- a/test/SolidityCompiler.cpp +++ b/test/SolidityCompiler.cpp @@ -96,7 +96,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) "}\n"; bytes code = compileContract(sourceCode); - unsigned boilerplateSize = 69; + unsigned boilerplateSize = 70; bytes expectation({byte(Instruction::JUMPDEST), byte(Instruction::PUSH1), 0x0, // initialize local variable x byte(Instruction::PUSH1), 0x2, @@ -114,8 +114,8 @@ BOOST_AUTO_TEST_CASE(ifStatement) " function f() { bool x; if (x) 77; else if (!x) 78; else 79; }" "}\n"; bytes code = compileContract(sourceCode); - unsigned shift = 56; - unsigned boilerplateSize = 69; + unsigned shift = 57; + unsigned boilerplateSize = 70; bytes expectation({byte(Instruction::JUMPDEST), byte(Instruction::PUSH1), 0x0, byte(Instruction::DUP1), @@ -155,8 +155,8 @@ BOOST_AUTO_TEST_CASE(loops) " function f() { while(true){1;break;2;continue;3;return;4;} }" "}\n"; bytes code = compileContract(sourceCode); - unsigned shift = 56; - unsigned boilerplateSize = 69; + unsigned shift = 57; + unsigned boilerplateSize = 70; bytes expectation({byte(Instruction::JUMPDEST), byte(Instruction::JUMPDEST), byte(Instruction::PUSH1), 0x1, diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 0325c4c6a..103b11269 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -2283,9 +2283,9 @@ BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory) } )"; compileAndRun(sourceCode); - bytes calldata = bytes(61, 0x22) + bytes(12, 0x12); - sendMessage(calldata, false); - BOOST_CHECK(m_output == encodeArgs(dev::sha3(bytes{'a', 'b', 'c'} + calldata))); + bytes calldata1 = bytes(61, 0x22) + bytes(12, 0x12); + sendMessage(calldata1, false); + BOOST_CHECK(m_output == encodeArgs(dev::sha3(bytes{'a', 'b', 'c'} + calldata1))); } BOOST_AUTO_TEST_CASE(call_forward_bytes) @@ -2534,6 +2534,49 @@ BOOST_AUTO_TEST_CASE(constructing_enums_from_ints) BOOST_CHECK(callContractFunction("test()") == encodeArgs(1)); } +BOOST_AUTO_TEST_CASE(external_function) +{ + char const* sourceCode = R"( + contract c { + function f(uint a) returns (uint) { return a; } + function test(uint a, uint b) external returns (uint r_a, uint r_b) { + r_a = f(a + 7); + r_b = b; + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("test(uint256,uint256)", 2, 3) == encodeArgs(2+7, 3)); +} + +BOOST_AUTO_TEST_CASE(bytes_in_arguments) +{ + char const* sourceCode = R"( + contract c { + uint result; + function f(uint a, uint b) { result += a + b; } + function g(uint a) { result *= a; } + function test(uint a, bytes data1, bytes data2, uint b) external returns (uint r_a, uint r, uint r_b, uint l) { + r_a = a; + this.call(data1); + this.call(data2); + r = result; + r_b = b; + l = data1.length; + } + } + )"; + compileAndRun(sourceCode); + string innercalldata1 = asString(FixedHash<4>(dev::sha3("f(uint256,uint256)")).asBytes() + encodeArgs(8, 9)); + bytes calldata1 = encodeArgs(u256(innercalldata1.length()), 12, innercalldata1, 13); + string innercalldata2 = asString(FixedHash<4>(dev::sha3("g(uint256)")).asBytes() + encodeArgs(3)); + bytes calldata = encodeArgs( + u256(innercalldata1.length()), u256(innercalldata2.length()), + 12, innercalldata1, innercalldata2, 13); + BOOST_CHECK(callContractFunction("test(uint256,bytes,bytes,uint256)", calldata) + == encodeArgs(12, (8 + 9) * 3, 13, u256(innercalldata1.length()))); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index d6e4ed516..6b337ac74 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -1083,6 +1083,86 @@ BOOST_AUTO_TEST_CASE(enum_duplicate_values) BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError); } +BOOST_AUTO_TEST_CASE(private_visibility) +{ + char const* sourceCode = R"( + contract base { + function f() private {} + } + contract derived is base { + function g() { f(); } + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), DeclarationError); +} + +BOOST_AUTO_TEST_CASE(private_visibility_via_explicit_base_access) +{ + char const* sourceCode = R"( + contract base { + function f() private {} + } + contract derived is base { + function g() { base.f(); } + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); +} + +BOOST_AUTO_TEST_CASE(external_visibility) +{ + char const* sourceCode = R"( + contract c { + function f() external {} + function g() { f(); } + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), DeclarationError); +} + +BOOST_AUTO_TEST_CASE(external_base_visibility) +{ + char const* sourceCode = R"( + contract base { + function f() external {} + } + contract derived is base { + function g() { base.f(); } + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); +} + +BOOST_AUTO_TEST_CASE(external_argument_assign) +{ + char const* sourceCode = R"( + contract c { + function f(uint a) external { a = 1; } + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); +} + +BOOST_AUTO_TEST_CASE(external_argument_increment) +{ + char const* sourceCode = R"( + contract c { + function f(uint a) external { a++; } + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); +} + +BOOST_AUTO_TEST_CASE(external_argument_delete) +{ + char const* sourceCode = R"( + contract c { + function f(uint a) external { delete a; } + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/SolidityParser.cpp b/test/SolidityParser.cpp index af82f612a..5f9064e0c 100644 --- a/test/SolidityParser.cpp +++ b/test/SolidityParser.cpp @@ -735,6 +735,24 @@ BOOST_AUTO_TEST_CASE(malformed_enum_declaration) BOOST_CHECK_THROW(parseText(text), ParserError); } +BOOST_AUTO_TEST_CASE(external_function) +{ + char const* text = R"( + contract c { + function x() external {} + })"; + BOOST_CHECK_NO_THROW(parseTextExplainError(text)); +} + +BOOST_AUTO_TEST_CASE(external_variable) +{ + char const* text = R"( + contract c { + uint external x; + })"; + BOOST_CHECK_THROW(parseText(text), ParserError); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 5e7472105..ff6939a5f 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -504,6 +504,49 @@ void executeTests(const string& _name, const string& _testPathAppendix, std::fun } } +RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject& _tObj) +{ + //Construct Rlp of the given transaction + RLPStream rlpStream; + rlpStream.appendList(_tObj.size()); + + if (_tObj.count("nonce")) + rlpStream << bigint(_tObj["nonce"].get_str()); + + if (_tObj.count("gasPrice")) + rlpStream << bigint(_tObj["gasPrice"].get_str()); + + if (_tObj.count("gasLimit")) + rlpStream << bigint(_tObj["gasLimit"].get_str()); + + if (_tObj.count("to")) + { + if (_tObj["to"].get_str().empty()) + rlpStream << ""; + else + rlpStream << importByteArray(_tObj["to"].get_str()); + } + + if (_tObj.count("value")) + rlpStream << bigint(_tObj["value"].get_str()); + + if (_tObj.count("data")) + rlpStream << importData(_tObj); + + if (_tObj.count("v")) + rlpStream << bigint(_tObj["v"].get_str()); + + if (_tObj.count("r")) + rlpStream << bigint(_tObj["r"].get_str()); + + if (_tObj.count("s")) + rlpStream << bigint(_tObj["s"].get_str()); + + if (_tObj.count("extrafield")) + rlpStream << bigint(_tObj["extrafield"].get_str()); + + return rlpStream; +} void processCommandLineOptions() { diff --git a/test/TestHelper.h b/test/TestHelper.h index ae6ea20cc..c4dde1a60 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -45,7 +45,7 @@ namespace test class ImportTest { public: - ImportTest() = default; + ImportTest(json_spirit::mObject& _o) : m_TestObject(_o) {} ImportTest(json_spirit::mObject& _o, bool isFiller); // imports @@ -79,6 +79,7 @@ void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _e void executeTests(const std::string& _name, const std::string& _testPathAppendix, std::function doTests); std::string getTestPath(); void userDefinedTest(std::string testTypeFlag, std::function doTests); +RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject& _tObj); void processCommandLineOptions(); eth::LastHashes lastHashes(u256 _currentBlockNumber); diff --git a/test/blInvalidHeaderTestFiller.json b/test/blInvalidHeaderTestFiller.json new file mode 100644 index 000000000..482eafc56 --- /dev/null +++ b/test/blInvalidHeaderTestFiller.json @@ -0,0 +1,687 @@ +{ + "log1_wrongBlockNumber" : { + "blockHeader" : { + "number" : "2" + }, + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + }, + + "log1_wrongBloom" : { + "blockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + }, + + "wrongCoinbase" : { + "blockHeader" : { + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1" + }, + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + }, + + "wrongDifficulty" : { + "blockHeader" : { + "difficulty" : "10000" + }, + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + }, + + "DifferentExtraData" : { + "blockHeader" : { + "extraData" : "42" + }, + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + }, + + "wrongGasLimit" : { + "blockHeader" : { + "gasLimit" : "100000" + }, + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + }, + + "wrongGasUsed" : { + "blockHeader" : { + "gasUsed" : "0" + }, + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + }, + + "wrongNumber" : { + "blockHeader" : { + "number" : "0" + }, + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + }, + + "wrongParentHash" : { + "blockHeader" : { + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + }, + + "wrongReceiptTrie" : { + "blockHeader" : { + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + }, + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + }, + + "wrongStateRoot" : { + "blockHeader" : { + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a" + }, + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + }, + + "wrongTimestamp" : { + "blockHeader" : { + "timestamp" : "0x54c98c80" + }, + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + }, + + "wrongTransactionsTrie" : { + "blockHeader" : { + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + }, + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + }, + + "wrongUncleHash" : { + "blockHeader" : { + "uncleHash" : "0x0dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + } +} diff --git a/test/blValidBlockTestFiller.json b/test/blValidBlockTestFiller.json new file mode 100644 index 000000000..8099c0dd6 --- /dev/null +++ b/test/blValidBlockTestFiller.json @@ -0,0 +1,381 @@ +{ + "diffTooLowToChange" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "1023", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "850", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + + "diff1024" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "1024", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "850", + "gasPrice" : "1", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + + "gasPrice0" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "850", + "gasPrice" : "0", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + + "gasLimitTooHigh" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "1000000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "850", + "gasPrice" : "0", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + + "SimpleTx" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "500", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + + "txOrder" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "500", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "7000000000" + }, + { + "data" : "", + "gasLimit" : "500", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "8000000000" + } + ], + "uncleHeaders" : [ + ] + }, + + "txEqualValue" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "500", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + }, + { + "data" : "", + "gasLimit" : "500", + "gasPrice" : "9", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + }, + + "log1_correct" : { + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ], + + "firstBlockTest" : { + "block" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "023101", + "extraData" : "42", + "gasLimit" : "0x0dddb6", + "gasUsed" : "100", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "62", + "parentHash" : "0xefb4db878627027c81b3bb1c7dd3a18dae3914a49cdd24a3e40ab3bbfbb240c5", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + }, + "transactions" : [ + { + "data" : "0x60056013565b6101918061001d6000396000f35b3360008190555056006001600060e060020a6000350480630a874df61461003a57806341c0e1b514610058578063a02b161e14610066578063dbbdf0831461007757005b610045600435610149565b80600160a060020a031660005260206000f35b610060610161565b60006000f35b6100716004356100d4565b60006000f35b61008560043560243561008b565b60006000f35b600054600160a060020a031632600160a060020a031614156100ac576100b1565b6100d0565b8060018360005260205260406000208190555081600060005260206000a15b5050565b600054600160a060020a031633600160a060020a031614158015610118575033600160a060020a0316600182600052602052604060002054600160a060020a031614155b61012157610126565b610146565b600060018260005260205260406000208190555080600060005260206000a15b50565b60006001826000526020526040600020549050919050565b600054600160a060020a031633600160a060020a0316146101815761018f565b600054600160a060020a0316ff5b56", + "gasLimit" : "0x0f3e6f", + "gasPrice" : "0x09184e72a000", + "nonce" : "0", + "r" : "0xd4287e915ebac7a8af390560fa53c8f0b7f13802ba0393d7afa5823c2560ca89", + "s" : "0xae75db31a34f7e386ad459646de98ec3a1c88cc91b11620b4ffd86871f579942", + "to" : "", + "v" : "0x1b", + "value" : "" + } + ], + } + + } +} + diff --git a/test/block.cpp b/test/block.cpp new file mode 100644 index 000000000..ce165bc42 --- /dev/null +++ b/test/block.cpp @@ -0,0 +1,509 @@ +/* + 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 block.cpp + * @author Christoph Jentzsch + * @date 2015 + * block test functions. + */ + +#include +#include +#include "TestHelper.h" + +using namespace std; +using namespace json_spirit; +using namespace dev; +using namespace dev::eth; + +namespace dev { namespace test { + +bytes createBlockRLPFromFields(mObject& _tObj) +{ + RLPStream rlpStream; + rlpStream.appendList(_tObj.size()); + + if (_tObj.count("parentHash")) + rlpStream << importByteArray(_tObj["parentHash"].get_str()); + + if (_tObj.count("uncleHash")) + rlpStream << importByteArray(_tObj["uncleHash"].get_str()); + + if (_tObj.count("coinbase")) + rlpStream << importByteArray(_tObj["coinbase"].get_str()); + + if (_tObj.count("stateRoot")) + rlpStream << importByteArray(_tObj["stateRoot"].get_str()); + + if (_tObj.count("transactionsTrie")) + rlpStream << importByteArray(_tObj["transactionsTrie"].get_str()); + + if (_tObj.count("receiptTrie")) + rlpStream << importByteArray(_tObj["receiptTrie"].get_str()); + + if (_tObj.count("bloom")) + rlpStream << importByteArray(_tObj["bloom"].get_str()); + + if (_tObj.count("difficulty")) + rlpStream << bigint(_tObj["difficulty"].get_str()); + + if (_tObj.count("number")) + rlpStream << bigint(_tObj["number"].get_str()); + + if (_tObj.count("gasLimit")) + rlpStream << bigint(_tObj["gasLimit"].get_str()); + + if (_tObj.count("gasUsed")) + rlpStream << bigint(_tObj["gasUsed"].get_str()); + + if (_tObj.count("timestamp")) + rlpStream << bigint(_tObj["timestamp"].get_str()); + + if (_tObj.count("extraData")) + rlpStream << importByteArray(_tObj["extraData"].get_str()); + + if (_tObj.count("nonce")) + rlpStream << importByteArray(_tObj["nonce"].get_str()); + + return rlpStream.out(); +} + +void doBlockTests(json_spirit::mValue& _v, bool _fillin) +{ + for (auto& i: _v.get_obj()) + { + cerr << i.first << endl; + mObject& o = i.second.get_obj(); + + BOOST_REQUIRE(o.count("genesisBlockHeader")); + BlockInfo blockFromFields; + try + { + // construct genesis block + const bytes c_blockRLP = createBlockRLPFromFields(o["genesisBlockHeader"].get_obj()); + const RLP c_bRLP(c_blockRLP); + blockFromFields.populateFromHeader(c_bRLP, false); + } + catch (Exception const& _e) + { + cnote << "block population did throw an exception: " << diagnostic_information(_e); + BOOST_ERROR("Failed block population with Exception: " << _e.what()); + continue; + } + catch (std::exception const& _e) + { + BOOST_ERROR("Failed block population with Exception: " << _e.what()); + continue; + } + catch(...) + { + cnote << "block population did throw an unknown exception\n"; + continue; + } + + BOOST_REQUIRE(o.count("pre")); + + ImportTest importer(o["pre"].get_obj()); + State state(Address(), OverlayDB(), BaseState::Empty); + importer.importState(o["pre"].get_obj(), state); + state.commit(); + + if (_fillin) + blockFromFields.stateRoot = state.rootHash(); + else + BOOST_CHECK_MESSAGE(blockFromFields.stateRoot == state.rootHash(), "root hash does not match"); + + if (_fillin) + { + // find new valid nonce + ProofOfWork pow; + MineInfo ret; + while (!ProofOfWork::verify(blockFromFields.headerHash(WithoutNonce), blockFromFields.nonce, blockFromFields.difficulty)) + tie(ret, blockFromFields.nonce) = pow.mine(blockFromFields.headerHash(WithoutNonce), blockFromFields.difficulty, 1000, true, true); + + //update genesis block in json file + o["genesisBlockHeader"].get_obj()["stateRoot"] = toString(blockFromFields.stateRoot); + o["genesisBlockHeader"].get_obj()["nonce"] = toString(blockFromFields.nonce); + } + + // create new "genesis" block + RLPStream rlpStream; + blockFromFields.streamRLP(rlpStream, WithNonce); + + RLPStream block(3); + block.appendRaw(rlpStream.out()); + block.appendRaw(RLPEmptyList); + block.appendRaw(RLPEmptyList); + + blockFromFields.verifyInternals(&block.out()); + + // construct blockchain + BlockChain bc(block.out(), string(), true); + + if (_fillin) + { + BOOST_REQUIRE(o.count("transactions")); + + TransactionQueue txs; + + for (auto const& txObj: o["transactions"].get_array()) + { + mObject tx = txObj.get_obj(); + importer.importTransaction(tx); + if (!txs.attemptImport(importer.m_transaction.rlp())) + cnote << "failed importing transaction\n"; + } + + try + { + state.sync(bc); + state.sync(bc,txs); + state.commitToMine(bc); + MineInfo info; + for (info.completed = false; !info.completed; info = state.mine()) {} + state.completeMine(); + } + catch (Exception const& _e) + { + cnote << "state sync or mining did throw an exception: " << diagnostic_information(_e); + return; + } + catch (std::exception const& _e) + { + cnote << "state sync or mining did throw an exception: " << _e.what(); + return; + } + + // write valid txs + mArray txArray; + Transactions txList; + for (auto const& txi: txs.transactions()) + { + Transaction tx(txi.second, CheckSignature::Sender); + txList.push_back(tx); + mObject txObject; + txObject["nonce"] = toString(tx.nonce()); + txObject["data"] = toHex(tx.data()); + txObject["gasLimit"] = toString(tx.gas()); + txObject["gasPrice"] = toString(tx.gasPrice()); + txObject["r"] = "0x" + toString(tx.signature().r); + txObject["s"] = "0x" + toString(tx.signature().s); + txObject["v"] = to_string(tx.signature().v + 27); + txObject["to"] = toString(tx.receiveAddress()); + txObject["value"] = toString(tx.value()); + + txArray.push_back(txObject); + } + + o["transactions"] = txArray; + o["rlp"] = "0x" + toHex(state.blockData()); + + BlockInfo current_BlockHeader = state.info(); + + // overwrite blockheader with (possible wrong) data from "blockheader" in filler; + + if (o.count("blockHeader")) + { + if (o["blockHeader"].get_obj().size() != 14) + { + + BlockInfo tmp = current_BlockHeader; + + if (o["blockHeader"].get_obj().count("parentHash")) + tmp.parentHash = h256(o["blockHeader"].get_obj()["parentHash"].get_str()); + + if (o["blockHeader"].get_obj().count("uncleHash")) + tmp.sha3Uncles = h256(o["blockHeader"].get_obj()["uncleHash"].get_str()); + + if (o["blockHeader"].get_obj().count("coinbase")) + tmp.coinbaseAddress = Address(o["blockHeader"].get_obj()["coinbase"].get_str()); + + if (o["blockHeader"].get_obj().count("stateRoot")) + tmp.stateRoot = h256(o["blockHeader"].get_obj()["stateRoot"].get_str()); + + if (o["blockHeader"].get_obj().count("transactionsTrie")) + tmp.transactionsRoot = h256(o["blockHeader"].get_obj()["transactionsTrie"].get_str()); + + if (o["blockHeader"].get_obj().count("receiptTrie")) + tmp.receiptsRoot = h256(o["blockHeader"].get_obj()["receiptTrie"].get_str()); + + if (o["blockHeader"].get_obj().count("bloom")) + tmp.logBloom = LogBloom(o["blockHeader"].get_obj()["bloom"].get_str()); + + if (o["blockHeader"].get_obj().count("difficulty")) + tmp.difficulty = toInt(o["blockHeader"].get_obj()["difficulty"]); + + if (o["blockHeader"].get_obj().count("number")) + tmp.number = toInt(o["blockHeader"].get_obj()["number"]); + + if (o["blockHeader"].get_obj().count("gasLimit")) + tmp.gasLimit = toInt(o["blockHeader"].get_obj()["gasLimit"]); + + if (o["blockHeader"].get_obj().count("gasUsed")) + tmp.gasUsed = toInt(o["blockHeader"].get_obj()["gasUsed"]); + + if (o["blockHeader"].get_obj().count("timestamp")) + tmp.timestamp = toInt(o["blockHeader"].get_obj()["timestamp"]); + + if (o["blockHeader"].get_obj().count("extraData")) + tmp.extraData = importByteArray(o["blockHeader"].get_obj()["extraData"].get_str()); + + // find new valid nonce + + if (tmp != current_BlockHeader) + { + current_BlockHeader = tmp; + cout << "new header!\n"; + ProofOfWork pow; + MineInfo ret; + while (!ProofOfWork::verify(current_BlockHeader.headerHash(WithoutNonce), current_BlockHeader.nonce, current_BlockHeader.difficulty)) + tie(ret, current_BlockHeader.nonce) = pow.mine(current_BlockHeader.headerHash(WithoutNonce), current_BlockHeader.difficulty, 10000, true, true); + } + } + else + { + // take the blockheader as is + const bytes c_blockRLP = createBlockRLPFromFields(o["blockHeader"].get_obj()); + const RLP c_bRLP(c_blockRLP); + current_BlockHeader.populateFromHeader(c_bRLP, false); + } + } + + // write block header + + mObject oBlockHeader; + oBlockHeader["parentHash"] = toString(current_BlockHeader.parentHash); + oBlockHeader["uncleHash"] = toString(current_BlockHeader.sha3Uncles); + oBlockHeader["coinbase"] = toString(current_BlockHeader.coinbaseAddress); + oBlockHeader["stateRoot"] = toString(current_BlockHeader.stateRoot); + oBlockHeader["transactionsTrie"] = toString(current_BlockHeader.transactionsRoot); + oBlockHeader["receiptTrie"] = toString(current_BlockHeader.receiptsRoot); + oBlockHeader["bloom"] = toString(current_BlockHeader.logBloom); + oBlockHeader["difficulty"] = toString(current_BlockHeader.difficulty); + oBlockHeader["number"] = toString(current_BlockHeader.number); + oBlockHeader["gasLimit"] = toString(current_BlockHeader.gasLimit); + oBlockHeader["gasUsed"] = toString(current_BlockHeader.gasUsed); + oBlockHeader["timestamp"] = toString(current_BlockHeader.timestamp); + oBlockHeader["extraData"] = toHex(current_BlockHeader.extraData); + oBlockHeader["nonce"] = toString(current_BlockHeader.nonce); + + o["blockHeader"] = oBlockHeader; + + // write uncle list + mArray aUncleList; // as of now, our parent is always the genesis block, so we can not have uncles. + o["uncleHeaders"] = aUncleList; + + //txs: + + RLPStream txStream; + txStream.appendList(txList.size()); + for (unsigned i = 0; i < txList.size(); ++i) + { + RLPStream txrlp; + txList[i].streamRLP(txrlp); + txStream.appendRaw(txrlp.out()); + } + + RLPStream rlpStream2; + current_BlockHeader.streamRLP(rlpStream2, WithNonce); + + RLPStream block2(3); + block2.appendRaw(rlpStream2.out()); + block2.appendRaw(txStream.out()); + block2.appendRaw(RLPEmptyList); + + o["rlp"] = "0x" + toHex(block2.out()); + + if (sha3(RLP(state.blockData())[0].data()) != sha3(RLP(block2.out())[0].data())) + cnote << "block header mismatch\n"; + + if (sha3(RLP(state.blockData())[1].data()) != sha3(RLP(block2.out())[1].data())) + cnote << "txs mismatch\n"; + + if (sha3(RLP(state.blockData())[2].data()) != sha3(RLP(block2.out())[2].data())) + cnote << "uncle list mismatch\n"; + + try + { + ImportTest importerTmp(o["pre"].get_obj()); + State stateTmp(Address(), OverlayDB(), BaseState::Empty); + importerTmp.importState(o["pre"].get_obj(), stateTmp); + stateTmp.commit(); + BlockChain bcTmp(block.out(), getDataDir() + "/tmpBlockChain.bc", true); + stateTmp.sync(bcTmp); + bc.import(block2.out(), stateTmp.db()); + stateTmp.sync(bcTmp); + } + // if exception is thrown, RLP is invalid and no blockHeader, Transaction list, or Uncle list should be given + catch (...) + { + cnote << "block is invalid!\n"; + o.erase(o.find("blockHeader")); + o.erase(o.find("uncleHeaders")); + o.erase(o.find("transactions")); + } + } + + else + { + bytes blockRLP; + try + { + state.sync(bc); + blockRLP = importByteArray(o["rlp"].get_str()); + bc.import(blockRLP, state.db()); + state.sync(bc); + } + // if exception is thrown, RLP is invalid and no blockHeader, Transaction list, or Uncle list should be given + catch (Exception const& _e) + { + cnote << "state sync or block import did throw an exception: " << diagnostic_information(_e); + BOOST_CHECK(o.count("blockHeader") == 0); + BOOST_CHECK(o.count("transactions") == 0); + BOOST_CHECK(o.count("uncleHeaders") == 0); + continue; + } + catch (std::exception const& _e) + { + cnote << "state sync or block import did throw an exception: " << _e.what(); + BOOST_CHECK(o.count("blockHeader") == 0); + BOOST_CHECK(o.count("transactions") == 0); + BOOST_CHECK(o.count("uncleHeaders") == 0); + continue; + } + catch(...) + { + cnote << "state sync or block import did throw an exception\n"; + BOOST_CHECK(o.count("blockHeader") == 0); + BOOST_CHECK(o.count("transactions") == 0); + BOOST_CHECK(o.count("uncleHeaders") == 0); + continue; + } + + BOOST_REQUIRE(o.count("blockHeader")); + + mObject tObj = o["blockHeader"].get_obj(); + BlockInfo blockHeaderFromFields; + const bytes c_rlpBytesBlockHeader = createBlockRLPFromFields(tObj); + const RLP c_blockHeaderRLP(c_rlpBytesBlockHeader); + blockHeaderFromFields.populateFromHeader(c_blockHeaderRLP, false); + + BlockInfo blockFromRlp = bc.info(); + + //Check the fields restored from RLP to original fields + BOOST_CHECK_MESSAGE(blockHeaderFromFields.headerHash(WithNonce) == blockFromRlp.headerHash(WithNonce), "hash in given RLP not matching the block hash!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.parentHash == blockFromRlp.parentHash, "parentHash in given RLP not matching the block parentHash!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.sha3Uncles == blockFromRlp.sha3Uncles, "sha3Uncles in given RLP not matching the block sha3Uncles!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.coinbaseAddress == blockFromRlp.coinbaseAddress,"coinbaseAddress in given RLP not matching the block coinbaseAddress!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.stateRoot == blockFromRlp.stateRoot, "stateRoot in given RLP not matching the block stateRoot!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.transactionsRoot == blockFromRlp.transactionsRoot, "transactionsRoot in given RLP not matching the block transactionsRoot!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.receiptsRoot == blockFromRlp.receiptsRoot, "receiptsRoot in given RLP not matching the block receiptsRoot!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.logBloom == blockFromRlp.logBloom, "logBloom in given RLP not matching the block logBloom!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.difficulty == blockFromRlp.difficulty, "difficulty in given RLP not matching the block difficulty!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.number == blockFromRlp.number, "number in given RLP not matching the block number!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.gasLimit == blockFromRlp.gasLimit,"gasLimit in given RLP not matching the block gasLimit!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.gasUsed == blockFromRlp.gasUsed, "gasUsed in given RLP not matching the block gasUsed!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.timestamp == blockFromRlp.timestamp, "timestamp in given RLP not matching the block timestamp!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.extraData == blockFromRlp.extraData, "extraData in given RLP not matching the block extraData!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.nonce == blockFromRlp.nonce, "nonce in given RLP not matching the block nonce!"); + + BOOST_CHECK_MESSAGE(blockHeaderFromFields == blockFromRlp, "However, blockHeaderFromFields != blockFromRlp!"); + + //Check transaction list + + Transactions txsFromField; + + for (auto const& txObj: o["transactions"].get_array()) + { + mObject tx = txObj.get_obj(); + + BOOST_REQUIRE(tx.count("nonce")); + BOOST_REQUIRE(tx.count("gasPrice")); + BOOST_REQUIRE(tx.count("gasLimit")); + BOOST_REQUIRE(tx.count("to")); + BOOST_REQUIRE(tx.count("value")); + BOOST_REQUIRE(tx.count("v")); + BOOST_REQUIRE(tx.count("r")); + BOOST_REQUIRE(tx.count("s")); + BOOST_REQUIRE(tx.count("data")); + + try + { + Transaction t(createRLPStreamFromTransactionFields(tx).out(), CheckSignature::Sender); + txsFromField.push_back(t); + } + catch (Exception const& _e) + { + BOOST_ERROR("Failed transaction constructor with Exception: " << diagnostic_information(_e)); + } + catch (exception const& _e) + { + cnote << _e.what(); + } + } + + Transactions txsFromRlp; + RLP root(blockRLP); + for (auto const& tr: root[1]) + { + Transaction tx(tr.data(), CheckSignature::Sender); + txsFromRlp.push_back(tx); + } + + BOOST_CHECK_MESSAGE(txsFromRlp.size() == txsFromField.size(), "transaction list size does not match"); + + for (size_t i = 0; i < txsFromField.size(); ++i) + { + BOOST_CHECK_MESSAGE(txsFromField[i].data() == txsFromRlp[i].data(), "transaction data in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].gas() == txsFromRlp[i].gas(), "transaction gasLimit in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].gasPrice() == txsFromRlp[i].gasPrice(), "transaction gasPrice in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].nonce() == txsFromRlp[i].nonce(), "transaction nonce in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].signature().r == txsFromRlp[i].signature().r, "transaction r in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].signature().s == txsFromRlp[i].signature().s, "transaction s in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].signature().v == txsFromRlp[i].signature().v, "transaction v in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].receiveAddress() == txsFromRlp[i].receiveAddress(), "transaction receiveAddress in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].value() == txsFromRlp[i].value(), "transaction receiveAddress in rlp and in field do not match"); + + BOOST_CHECK_MESSAGE(txsFromField[i] == txsFromRlp[i], "transactions in rlp and in transaction field do not match"); + } + + // check uncle list + BOOST_CHECK_MESSAGE((o["uncleList"].type() == json_spirit::null_type ? 0 : o["uncleList"].get_array().size()) == 0, "Uncle list is not empty, but the genesis block can not have uncles"); + } + } +} + +} }// Namespace Close + + +BOOST_AUTO_TEST_SUITE(BlockTests) + +BOOST_AUTO_TEST_CASE(blValidBlockTest) +{ + dev::test::executeTests("blValidBlockTest", "/BlockTests", dev::test::doBlockTests); +} + +BOOST_AUTO_TEST_CASE(blInvalidHeaderTest) +{ + dev::test::executeTests("blInvalidHeaderTest", "/BlockTests", dev::test::doBlockTests); +} + +BOOST_AUTO_TEST_CASE(userDefinedFileBl) +{ + dev::test::userDefinedTest("--bltest", dev::test::doBlockTests); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/stSystemOperationsTestFiller.json b/test/stSystemOperationsTestFiller.json index eae393645..9f47b2fef 100644 --- a/test/stSystemOperationsTestFiller.json +++ b/test/stSystemOperationsTestFiller.json @@ -81,13 +81,13 @@ "pre" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "1000000000000000000", - "nonce" : 0, + "nonce" : "0", "code" : "0x444242424245434253f0", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", - "nonce" : 0, + "nonce" : "0", "code" : "", "storage": {} } diff --git a/test/transaction.cpp b/test/transaction.cpp index 9f9429534..7bd8ac20c 100644 --- a/test/transaction.cpp +++ b/test/transaction.cpp @@ -21,6 +21,7 @@ */ #include "TestHelper.h" + using namespace std; using namespace json_spirit; using namespace dev; @@ -28,50 +29,6 @@ using namespace dev::eth; namespace dev { namespace test { -RLPStream createRLPStreamFromTransactionFields(mObject& _tObj) -{ - //Construct Rlp of the given transaction - RLPStream rlpStream; - rlpStream.appendList(_tObj.size()); - - if (_tObj.count("nonce") > 0) - rlpStream << bigint(_tObj["nonce"].get_str()); - - if (_tObj.count("gasPrice") > 0) - rlpStream << bigint(_tObj["gasPrice"].get_str()); - - if (_tObj.count("gasLimit") > 0) - rlpStream << bigint(_tObj["gasLimit"].get_str()); - - if (_tObj.count("to") > 0) - { - if (_tObj["to"].get_str().empty()) - rlpStream << ""; - else - rlpStream << importByteArray(_tObj["to"].get_str()); - } - - if (_tObj.count("value") > 0) - rlpStream << bigint(_tObj["value"].get_str()); - - if (_tObj.count("data") > 0) - rlpStream << importData(_tObj); - - if (_tObj.count("v") > 0) - rlpStream << bigint(_tObj["v"].get_str()); - - if (_tObj.count("r") > 0) - rlpStream << bigint(_tObj["r"].get_str()); - - if (_tObj.count("s") > 0) - rlpStream << bigint(_tObj["s"].get_str()); - - if (_tObj.count("extrafield") > 0) - rlpStream << bigint(_tObj["extrafield"].get_str()); - - return rlpStream; -} - void doTransactionTests(json_spirit::mValue& _v, bool _fillin) { for (auto& i: _v.get_obj()) @@ -115,7 +72,6 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) Address addressReaded = Address(o["sender"].get_str()); BOOST_CHECK_MESSAGE(txFromFields.sender() == addressReaded || txFromRlp.sender() == addressReaded, "Signature address of sender does not match given sender address!"); - } else { @@ -141,6 +97,7 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) } }//for }//doTransactionTests + } }// Namespace Close diff --git a/test/vmPerformanceTestFiller.json b/test/vmPerformanceTestFiller.json index 3292916ec..e33bd1955 100644 --- a/test/vmPerformanceTestFiller.json +++ b/test/vmPerformanceTestFiller.json @@ -1,4 +1,33 @@ { + "manyFunctions100": { + "env" : { + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "currentNumber" : "0", + "currentGasLimit" : "100000000000", + "currentDifficulty" : "256", + "currentTimestamp" : "1", + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "1000000000000000000", + "nonce" : "0", + "//" : "ManyFunctions.sol", + "code" : "0x60e060020a60003504806301f99ad7146108c3578063023a624a146108d857806303bdecf5146108ed57806305fe035f14610902578063082d8f4914610917578063090bf3b71461092c5780630bd9c534146109415780630c4bfa94146109565780630e20ebe21461096b5780630f76de0d1461098057806310cfcc191461099557806313ce15a9146109aa578063140dcec4146109bf57806314d07a3e146109d45780631687f112146109e957806316eb6603146109fe578063172cf71714610a135780631bd6f59614610a285780631cdb857114610a3d5780631cf74ece14610a525780631d09ba2c14610a675780631f69aa5114610a7c578063223dcc7414610a9157806325e524d314610aa6578063261de7c414610abb5780632632924d14610ad05780632909cc5d14610ae55780632981699814610afa5780632a85a45d14610b0f5780632ca36da014610b245780632cbf1f0d14610b395780632d0f557314610b4e5780632d97867814610b6357806331db9efd14610b7857806332064db714610b8d57806332931fbb14610ba2578063355f51a014610bb7578063361bb34014610bcc578063364ddb0e14610be15780633792a01814610bf657806338c68f8f14610c0b57806338e586fd14610c20578063392d42ae14610c3557806339a87bd914610c4a5780633a95a33214610c5f5780633b8ecdf914610c745780633cf0659a14610c895780633eaf992314610c9e5780633fe97ead14610cb35780633ff11c8b14610cc8578063404efc5314610cdd578063407fce7b14610cf257806340c3b18714610d07578063440208c314610d1c57806344e86b2f14610d31578063455df57914610d465780634689ab4d14610d5b57806346be2e0c14610d70578063487cd86f14610d8557806348e6178214610d9a57806349d4a34414610daf5780634a0f597414610dc45780634bc24ec514610dd95780634c2fe45614610dee5780634cc885d414610e035780634eaaad7b14610e185780634eb166af14610e2d5780635050093414610e42578063506bff1114610e57578063508762c114610e6c578063526938f814610e8157806354400c6014610e96578063559510d814610eab57806355a5f70214610ec057806356ca528f14610ed5578063570a2a1614610eea5780635dab2e0f14610eff5780635dca53d314610f1457806362017ebc14610f29578063621a25f814610f3e578063626d4a3614610f5357806362b6a28214610f6857806364faf22c14610f7d57806366d7ffde14610f9257806367b886e814610fa757806367e902c714610fbc57806369d7774014610fd15780636b7ae8e614610fe65780636c3b659114610ffb5780636e54181e146110105780636e978d91146110255780636f63d2ec1461103a578063706332d11461104f57806370ac4bb9146110645780637138ef521461107957806371dd46a91461108e57806372a7c229146110a35780637376fc8d146110b8578063738a2679146110cd57806374552650146110e2578063746fc8d0146110f757806379254bb81461110c5780637adaa3f8146111215780637e4eb35b14611136578063885ec18e1461114b5780638b9ff6b6146111605780638ce113dc146111755780638defbc5e1461118a5780638f4613d51461119f5780638fdc24ba146111b45780639002dba4146111c957806391d15735146111de57806391d43b23146111f357806393b14daa1461120857806394d63afd1461121d57806395805dad1461123257806396f68782146112475780639740e4a21461125c578063981290131461127157806399a3f0e8146112865780639acb1ad41461129b5780639be07908146112b05780639c15be0b146112c55780639d451c4d146112da5780639d8ee943146112ef5780639ef6ca0f14611304578063a0db0a2214611319578063a18e2eb91461132e578063a408384914611343578063a57544da14611358578063a5a83e4d1461136d578063a6843f3414611382578063a6dacdd714611397578063a8c4c8bc146113ac578063aa058a73146113c1578063aad62da2146113d6578063aaf3e4f4146113eb578063ab81e77314611400578063abc93aee14611415578063abde33f71461142a578063b114b96c1461143f578063b3df873714611454578063b4174cb014611469578063b5d02a561461147e578063b731e84814611493578063b7b96723146114a8578063bbcded7a146114bd578063bbececa9146114d2578063beca7440146114e7578063bf8981c0146114fc578063c028c67414611511578063c2385fa614611526578063c319a02c1461153b578063c569bae014611550578063c6715f8114611565578063c7b98dec1461157a578063c9acab841461158f578063ca9efc73146115a4578063cad80024146115b9578063cdadb0fa146115ce578063cdbdf391146115e3578063cf460fa5146115f8578063cf69318a1461160d578063d1835b8c14611622578063d353a1cb14611637578063d3e141e01461164c578063d5ec7e1d14611661578063d7ead1de14611676578063d90b02aa1461168b578063d959e244146116a0578063d9e68b44146116b5578063daacb24f146116ca578063dc12a805146116df578063dd946033146116f4578063dda5142414611709578063de6612171461171e578063dfb9560c14611733578063e03827d214611748578063e21720001461175d578063e2c718d814611772578063e3da539914611787578063e48e603f1461179c578063e5f9ec29146117b1578063e6c0459a146117c6578063e70addec146117db578063e7a01215146117f0578063ea7f4d2714611805578063ebb6c59f1461181a578063ed6302be1461182f578063ed64b36b14611844578063eecd278914611859578063f0ed14e01461186e578063f0f2134414611883578063f1e328f914611898578063f1e6f4cd146118ad578063f32fe995146118c2578063f75165c6146118d7578063f7ed71d0146118ec578063f80f44f314611901578063f8bc050514611916578063fbd3c51a1461192b578063fd72009014611940578063fed3a3001461195557005b6108ce600435612edf565b8060005260206000f35b6108e3600435612fb5565b8060005260206000f35b6108f8600435613f47565b8060005260206000f35b61090d600435612a11565b8060005260206000f35b6109226004356127ec565b8060005260206000f35b61093760043561215c565b8060005260206000f35b61094c6004356128c2565b8060005260206000f35b61096160043561310f565b8060005260206000f35b610976600435614e0b565b8060005260206000f35b61098b600435613269565b8060005260206000f35b6109a0600435611a82565b8060005260206000f35b6109b5600435613e71565b8060005260206000f35b6109ca600435611dd2565b8060005260206000f35b6109df6004356120d0565b8060005260206000f35b6109f4600435613755565b8060005260206000f35b610a096004356134e3565b8060005260206000f35b610a1e6004356137e1565b8060005260206000f35b610a3360043561382b565b8060005260206000f35b610a48600435612b0b565b8060005260206000f35b610a5d60043561386d565b8060005260206000f35b610a726004356131e5565b8060005260206000f35b610a876004356143e9565b8060005260206000f35b610a9c60043561319b565b8060005260206000f35b610ab1600435612e11565b8060005260206000f35b610ac660043561234a565b8060005260206000f35b610adb6004356121e8565b8060005260206000f35b610af06004356119f6565b8060005260206000f35b610b05600435613bff565b8060005260206000f35b610b1a600435612606565b8060005260206000f35b610b2f6004356126d4565b8060005260206000f35b610b44600435613bb5565b8060005260206000f35b610b59600435612462565b8060005260206000f35b610b6e600435611e14565b8060005260206000f35b610b836004356149ab565b8060005260206000f35b610b98600435611c26565b8060005260206000f35b610bad600435612a7f565b8060005260206000f35b610bc2600435613457565b8060005260206000f35b610bd760043561340d565b8060005260206000f35b610bec60043561363d565b8060005260206000f35b610c01600435612e53565b8060005260206000f35b610c1660043561477b565b8060005260206000f35b610c2b600435612c6d565b8060005260206000f35b610c40600435612648565b8060005260206000f35b610c55600435612274565b8060005260206000f35b610c6a6004356138f9565b8060005260206000f35b610c7f600435612b55565b8060005260206000f35b610c94600435611eea565b8060005260206000f35b610ca9600435613ebb565b8060005260206000f35b610cbe600435613499565b8060005260206000f35b610cd3600435614807565b8060005260206000f35b610ce8600435611fb8565b8060005260206000f35b610cfd600435613083565b8060005260206000f35b610d126004356125bc565b8060005260206000f35b610d27600435613041565b8060005260206000f35b610d3c6004356140a1565b8060005260206000f35b610d516004356147bd565b8060005260206000f35b610d66600435611c70565b8060005260206000f35b610d7b600435612300565b8060005260206000f35b610d906004356123d6565b8060005260206000f35b610da5600435612c23565b8060005260206000f35b610dba600435614faf565b8060005260206000f35b610dcf600435612044565b8060005260206000f35b610de4600435613ae7565b8060005260206000f35b610df9600435614cf3565b8060005260206000f35b610e0e600435613d17565b8060005260206000f35b610e2360043561412d565b8060005260206000f35b610e38600435614177565b8060005260206000f35b610e4d60043561208e565b8060005260206000f35b610e62600435612dc7565b8060005260206000f35b610e77600435612f29565b8060005260206000f35b610e8c6004356124a4565b8060005260206000f35b610ea1600435611b58565b8060005260206000f35b610eb66004356136c9565b8060005260206000f35b610ecb600435613227565b8060005260206000f35b610ee0600435611acc565b8060005260206000f35b610ef5600435613687565b8060005260206000f35b610f0a6004356146a5565b8060005260206000f35b610f1f6004356121a6565b8060005260206000f35b610f346004356132f5565b8060005260206000f35b610f49600435613da3565b8060005260206000f35b610f5e60043561379f565b8060005260206000f35b610f73600435612878565b8060005260206000f35b610f88600435611b0e565b8060005260206000f35b610f9d600435611ea0565b8060005260206000f35b610fb2600435614ed9565b8060005260206000f35b610fc7600435614bdb565b8060005260206000f35b610fdc600435614c1d565b8060005260206000f35b610ff1600435614245565b8060005260206000f35b6110066004356146ef565b8060005260206000f35b61101b60043561428f565b8060005260206000f35b611030600435614ac3565b8060005260206000f35b611045600435613de5565b8060005260206000f35b61105a6004356132b3565b8060005260206000f35b61106f6004356122be565b8060005260206000f35b611084600435612e9d565b8060005260206000f35b611099600435611b9a565b8060005260206000f35b6110ae6004356127aa565b8060005260206000f35b6110c3600435613e2f565b8060005260206000f35b6110d8600435614849565b8060005260206000f35b6110ed600435614dc1565b8060005260206000f35b61110260043561333f565b8060005260206000f35b61111760043561211a565b8060005260206000f35b61112c600435612692565b8060005260206000f35b611141600435612904565b8060005260206000f35b611156600435612d3b565b8060005260206000f35b61116b600435614b91565b8060005260206000f35b611180600435613a5b565b8060005260206000f35b611195600435612232565b8060005260206000f35b6111aa600435612f6b565b8060005260206000f35b6111bf600435614d35565b8060005260206000f35b6111d4600435611a40565b8060005260206000f35b6111e9600435612ff7565b8060005260206000f35b6111fe60043561431b565b8060005260206000f35b611213600435613159565b8060005260206000f35b611228600435612b97565b8060005260206000f35b61123d600435612990565b8060005260206000f35b611252600435613b73565b8060005260206000f35b611267600435614961565b8060005260206000f35b61127c600435613381565b8060005260206000f35b611291600435613fd3565b8060005260206000f35b6112a660043561257a565b8060005260206000f35b6112bb600435614501565b8060005260206000f35b6112d0600435613d59565b8060005260206000f35b6112e56004356143a7565b8060005260206000f35b6112fa60043561405f565b8060005260206000f35b61130f60043561238c565b8060005260206000f35b611324600435612be1565b8060005260206000f35b611339600435613f89565b8060005260206000f35b61134e60043561294e565b8060005260206000f35b6113636004356124ee565b8060005260206000f35b611378600435614b4f565b8060005260206000f35b61138d6004356133cb565b8060005260206000f35b6113a26004356139cf565b8060005260206000f35b6113b7600435613c8b565b8060005260206000f35b6113cc600435612cf9565b8060005260206000f35b6113e1600435614a79565b8060005260206000f35b6113f66004356149ed565b8060005260206000f35b61140b600435613b29565b8060005260206000f35b611420600435613ccd565b8060005260206000f35b611435600435611f76565b8060005260206000f35b61144a600435614ff1565b8060005260206000f35b61145f600435613525565b8060005260206000f35b61147460043561356f565b8060005260206000f35b6114896004356129dc565b8060005260206000f35b61149e600435614ca9565b8060005260206000f35b6114b3600435612d85565b8060005260206000f35b6114c86004356141b9565b8060005260206000f35b6114dd600435614475565b8060005260206000f35b6114f26004356135fb565b8060005260206000f35b611507600435612530565b8060005260206000f35b61151c600435614663565b8060005260206000f35b611531600435614433565b8060005260206000f35b611546600435614f23565b8060005260206000f35b61155b600435614c67565b8060005260206000f35b611570600435611d3e565b8060005260206000f35b611585600435612a3d565b8060005260206000f35b61159a600435613a11565b8060005260206000f35b6115af600435614619565b8060005260206000f35b6115c4600435613985565b8060005260206000f35b6115d9600435613943565b8060005260206000f35b6115ee600435612418565b8060005260206000f35b6116036004356119b4565b8060005260206000f35b611618600435613a9d565b8060005260206000f35b61162d600435611cb2565b8060005260206000f35b6116426004356129d2565b8060005260206000f35b611657600435612caf565b8060005260206000f35b61166c600435611d88565b8060005260206000f35b611681600435614203565b8060005260206000f35b61169660043561458d565b8060005260206000f35b6116ab600435611f2c565b8060005260206000f35b6116c0600435612a23565b8060005260206000f35b6116d5600435612836565b8060005260206000f35b6116ea6004356138b7565b8060005260206000f35b6116ff6004356145d7565b8060005260206000f35b61171460043561454b565b8060005260206000f35b6117296004356142d1565b8060005260206000f35b61173e600435611e5e565b8060005260206000f35b611753600435614015565b8060005260206000f35b611768600435613c41565b8060005260206000f35b61177d600435611be4565b8060005260206000f35b611792600435614b05565b8060005260206000f35b6117a7600435613713565b8060005260206000f35b6117bc6004356135b1565b8060005260206000f35b6117d16004356144bf565b8060005260206000f35b6117e660043561491f565b8060005260206000f35b6117fb600435612ac9565b8060005260206000f35b6118106004356130cd565b8060005260206000f35b6118256004356140eb565b8060005260206000f35b61183a600435614f65565b8060005260206000f35b61184f60043561196a565b8060005260206000f35b6118646004356148d5565b8060005260206000f35b611879600435614d7f565b8060005260206000f35b61188e600435612002565b8060005260206000f35b6118a3600435613efd565b8060005260206000f35b6118b860043561271e565b8060005260206000f35b6118cd600435614e4d565b8060005260206000f35b6118e2600435611cfc565b8060005260206000f35b6118f7600435612760565b8060005260206000f35b61190c600435614e97565b8060005260206000f35b61192160043561435d565b8060005260206000f35b611936600435614731565b8060005260206000f35b61194b600435614893565b8060005260206000f35b611960600435614a37565b8060005260206000f35b6000600061197f61197a846129dc565b6129dc565b9050605d60020a811015611992576119a2565b61199b816119f6565b91506119ae565b6119ab816119b4565b91505b50919050565b600060006119c1836129dc565b9050605e60020a8110156119d4576119e4565b6119dd81611a40565b91506119f0565b6119ed81611a82565b91505b50919050565b60006000611a0b611a06846129dc565b6129dc565b9050605e60020a811015611a1e57611a2e565b611a2781611a82565b9150611a3a565b611a3781611a40565b91505b50919050565b60006000611a4d836129dc565b9050605f60020a811015611a6057611a70565b611a6981611acc565b9150611a7c565b611a7981611b0e565b91505b50919050565b60006000611a97611a92846129dc565b6129dc565b9050605f60020a811015611aaa57611aba565b611ab381611b0e565b9150611ac6565b611ac381611acc565b91505b50919050565b60006000611ad9836129dc565b9050606060020a811015611aec57611afc565b611af581611b58565b9150611b08565b611b0581611b9a565b91505b50919050565b60006000611b23611b1e846129dc565b6129dc565b9050606060020a811015611b3657611b46565b611b3f81611b9a565b9150611b52565b611b4f81611b58565b91505b50919050565b60006000611b65836129dc565b9050606160020a811015611b7857611b88565b611b8181611be4565b9150611b94565b611b9181611c26565b91505b50919050565b60006000611baf611baa846129dc565b6129dc565b9050606160020a811015611bc257611bd2565b611bcb81611c26565b9150611bde565b611bdb81611be4565b91505b50919050565b60006000611bf1836129dc565b9050606260020a811015611c0457611c14565b611c0d81611c70565b9150611c20565b611c1d81611cb2565b91505b50919050565b60006000611c3b611c36846129dc565b6129dc565b9050606260020a811015611c4e57611c5e565b611c5781611cb2565b9150611c6a565b611c6781611c70565b91505b50919050565b60006000611c7d836129dc565b9050606360020a811015611c9057611ca0565b611c9981611cfc565b9150611cac565b611ca981611d88565b91505b50919050565b60006000611cc7611cc2846129dc565b6129dc565b9050606360020a811015611cda57611cea565b611ce381611d88565b9150611cf6565b611cf381611cfc565b91505b50919050565b60006000611d09836129dc565b9050606460020a811015611d1c57611d2c565b611d2581611dd2565b9150611d38565b611d3581611e14565b91505b50919050565b60006000611d53611d4e846129dc565b6129dc565b9050607a60020a811015611d6657611d76565b611d6f81613269565b9150611d82565b611d7f81613227565b91505b50919050565b60006000611d9d611d98846129dc565b6129dc565b9050606460020a811015611db057611dc0565b611db981611e14565b9150611dcc565b611dc981611dd2565b91505b50919050565b60006000611ddf836129dc565b9050606560020a811015611df257611e02565b611dfb81611e5e565b9150611e0e565b611e0b81611ea0565b91505b50919050565b60006000611e29611e24846129dc565b6129dc565b9050606560020a811015611e3c57611e4c565b611e4581611ea0565b9150611e58565b611e5581611e5e565b91505b50919050565b60006000611e6b836129dc565b9050606660020a811015611e7e57611e8e565b611e8781611eea565b9150611e9a565b611e9781611f2c565b91505b50919050565b60006000611eb5611eb0846129dc565b6129dc565b9050606660020a811015611ec857611ed8565b611ed181611f2c565b9150611ee4565b611ee181611eea565b91505b50919050565b60006000611ef7836129dc565b9050606760020a811015611f0a57611f1a565b611f1381611f76565b9150611f26565b611f2381611fb8565b91505b50919050565b60006000611f41611f3c846129dc565b6129dc565b9050606760020a811015611f5457611f64565b611f5d81611fb8565b9150611f70565b611f6d81611f76565b91505b50919050565b60006000611f83836129dc565b9050606860020a811015611f9657611fa6565b611f9f81612002565b9150611fb2565b611faf81612044565b91505b50919050565b60006000611fcd611fc8846129dc565b6129dc565b9050606860020a811015611fe057611ff0565b611fe981612044565b9150611ffc565b611ff981612002565b91505b50919050565b6000600061200f836129dc565b9050606960020a81101561202257612032565b61202b8161208e565b915061203e565b61203b816120d0565b91505b50919050565b60006000612059612054846129dc565b6129dc565b9050606960020a81101561206c5761207c565b612075816120d0565b9150612088565b6120858161208e565b91505b50919050565b6000600061209b836129dc565b9050606a60020a8110156120ae576120be565b6120b78161211a565b91506120ca565b6120c78161215c565b91505b50919050565b600060006120e56120e0846129dc565b6129dc565b9050606a60020a8110156120f857612108565b6121018161215c565b9150612114565b6121118161211a565b91505b50919050565b60006000612127836129dc565b9050606b60020a81101561213a5761214a565b612143816121a6565b9150612156565b612153816121e8565b91505b50919050565b6000600061217161216c846129dc565b6129dc565b9050606b60020a81101561218457612194565b61218d816121e8565b91506121a0565b61219d816121a6565b91505b50919050565b600060006121b3836129dc565b9050606c60020a8110156121c6576121d6565b6121cf81612232565b91506121e2565b6121df81612274565b91505b50919050565b600060006121fd6121f8846129dc565b6129dc565b9050606c60020a81101561221057612220565b61221981612274565b915061222c565b61222981612232565b91505b50919050565b6000600061223f836129dc565b9050606d60020a81101561225257612262565b61225b816122be565b915061226e565b61226b81612300565b91505b50919050565b60006000612289612284846129dc565b6129dc565b9050606d60020a81101561229c576122ac565b6122a581612300565b91506122b8565b6122b5816122be565b91505b50919050565b600060006122cb836129dc565b9050606e60020a8110156122de576122ee565b6122e78161234a565b91506122fa565b6122f78161238c565b91505b50919050565b60006000612315612310846129dc565b6129dc565b9050606e60020a81101561232857612338565b6123318161238c565b9150612344565b6123418161234a565b91505b50919050565b60006000612357836129dc565b9050606f60020a81101561236a5761237a565b612373816123d6565b9150612386565b61238381612418565b91505b50919050565b600060006123a161239c846129dc565b6129dc565b9050606f60020a8110156123b4576123c4565b6123bd81612418565b91506123d0565b6123cd816123d6565b91505b50919050565b600060006123e3836129dc565b9050607060020a8110156123f657612406565b6123ff81612462565b9150612412565b61240f816124a4565b91505b50919050565b6000600061242d612428846129dc565b6129dc565b9050607060020a81101561244057612450565b612449816124a4565b915061245c565b61245981612462565b91505b50919050565b6000600061246f836129dc565b9050607160020a81101561248257612492565b61248b816124ee565b915061249e565b61249b81612530565b91505b50919050565b600060006124b96124b4846129dc565b6129dc565b9050607160020a8110156124cc576124dc565b6124d581612530565b91506124e8565b6124e5816124ee565b91505b50919050565b600060006124fb836129dc565b9050607260020a81101561250e5761251e565b6125178161257a565b915061252a565b612527816125bc565b91505b50919050565b60006000612545612540846129dc565b6129dc565b9050607260020a81101561255857612568565b612561816125bc565b9150612574565b6125718161257a565b91505b50919050565b60006000612587836129dc565b9050607360020a81101561259a576125aa565b6125a381612606565b91506125b6565b6125b381612648565b91505b50919050565b600060006125d16125cc846129dc565b6129dc565b9050607360020a8110156125e4576125f4565b6125ed81612648565b9150612600565b6125fd81612606565b91505b50919050565b60006000612613836129dc565b9050607460020a81101561262657612636565b61262f81612692565b9150612642565b61263f816126d4565b91505b50919050565b6000600061265d612658846129dc565b6129dc565b9050607460020a81101561267057612680565b612679816126d4565b915061268c565b61268981612692565b91505b50919050565b6000600061269f836129dc565b9050607560020a8110156126b2576126c2565b6126bb8161271e565b91506126ce565b6126cb81612760565b91505b50919050565b600060006126e96126e4846129dc565b6129dc565b9050607560020a8110156126fc5761270c565b61270581612760565b9150612718565b6127158161271e565b91505b50919050565b6000600061272b836129dc565b9050607660020a81101561273e5761274e565b612747816127aa565b915061275a565b612757816127ec565b91505b50919050565b60006000612775612770846129dc565b6129dc565b9050607660020a81101561278857612798565b612791816127ec565b91506127a4565b6127a1816127aa565b91505b50919050565b600060006127b7836129dc565b9050607760020a8110156127ca576127da565b6127d381612836565b91506127e6565b6127e381612878565b91505b50919050565b600060006128016127fc846129dc565b6129dc565b9050607760020a81101561281457612824565b61281d81612878565b9150612830565b61282d81612836565b91505b50919050565b60006000612843836129dc565b9050607860020a81101561285657612866565b61285f816128c2565b9150612872565b61286f81612904565b91505b50919050565b6000600061288d612888846129dc565b6129dc565b9050607860020a8110156128a0576128b0565b6128a981612904565b91506128bc565b6128b9816128c2565b91505b50919050565b600060006128cf836129dc565b9050607960020a8110156128e2576128f2565b6128eb8161294e565b91506128fe565b6128fb81611d3e565b91505b50919050565b60006000612919612914846129dc565b6129dc565b9050607960020a81101561292c5761293c565b61293581611d3e565b9150612948565b6129458161294e565b91505b50919050565b6000600061295b836129dc565b9050607a60020a81101561296e5761297e565b61297781613227565b915061298a565b61298781613269565b91505b50919050565b6000600061299d836129dc565b9050604e60020a8110156129b0576129c0565b6129b981612a7f565b91506129cc565b6129c981612a3d565b91505b50919050565b6000819050919050565b600060007f5851f42d4c957f2c0000000000000000000000000000000000000000000000019050828102600101915050919050565b6000612a1c826129d2565b9050919050565b6000612a36612a31836129dc565b6129d2565b9050919050565b60006000612a4a836129dc565b9050604f60020a811015612a5d57612a6d565b612a6681612ac9565b9150612a79565b612a7681612b0b565b91505b50919050565b60006000612a94612a8f846129dc565b6129dc565b9050604f60020a811015612aa757612ab7565b612ab081612b0b565b9150612ac3565b612ac081612ac9565b91505b50919050565b60006000612ad6836129dc565b9050605060020a811015612ae957612af9565b612af281612b55565b9150612b05565b612b0281612b97565b91505b50919050565b60006000612b20612b1b846129dc565b6129dc565b9050605060020a811015612b3357612b43565b612b3c81612b97565b9150612b4f565b612b4c81612b55565b91505b50919050565b60006000612b62836129dc565b9050605160020a811015612b7557612b85565b612b7e81612be1565b9150612b91565b612b8e81612c23565b91505b50919050565b60006000612bac612ba7846129dc565b6129dc565b9050605160020a811015612bbf57612bcf565b612bc881612c23565b9150612bdb565b612bd881612be1565b91505b50919050565b60006000612bee836129dc565b9050605260020a811015612c0157612c11565b612c0a81612c6d565b9150612c1d565b612c1a81612caf565b91505b50919050565b60006000612c38612c33846129dc565b6129dc565b9050605260020a811015612c4b57612c5b565b612c5481612caf565b9150612c67565b612c6481612c6d565b91505b50919050565b60006000612c7a836129dc565b9050605360020a811015612c8d57612c9d565b612c9681612cf9565b9150612ca9565b612ca681612d3b565b91505b50919050565b60006000612cc4612cbf846129dc565b6129dc565b9050605360020a811015612cd757612ce7565b612ce081612d3b565b9150612cf3565b612cf081612cf9565b91505b50919050565b60006000612d06836129dc565b9050605460020a811015612d1957612d29565b612d2281612d85565b9150612d35565b612d3281612dc7565b91505b50919050565b60006000612d50612d4b846129dc565b6129dc565b9050605460020a811015612d6357612d73565b612d6c81612dc7565b9150612d7f565b612d7c81612d85565b91505b50919050565b60006000612d92836129dc565b9050605560020a811015612da557612db5565b612dae81612e11565b9150612dc1565b612dbe81612e53565b91505b50919050565b60006000612ddc612dd7846129dc565b6129dc565b9050605560020a811015612def57612dff565b612df881612e53565b9150612e0b565b612e0881612e11565b91505b50919050565b60006000612e1e836129dc565b9050605660020a811015612e3157612e41565b612e3a81612e9d565b9150612e4d565b612e4a81612edf565b91505b50919050565b60006000612e68612e63846129dc565b6129dc565b9050605660020a811015612e7b57612e8b565b612e8481612edf565b9150612e97565b612e9481612e9d565b91505b50919050565b60006000612eaa836129dc565b9050605760020a811015612ebd57612ecd565b612ec681612f29565b9150612ed9565b612ed681612f6b565b91505b50919050565b60006000612ef4612eef846129dc565b6129dc565b9050605760020a811015612f0757612f17565b612f1081612f6b565b9150612f23565b612f2081612f29565b91505b50919050565b60006000612f36836129dc565b9050605860020a811015612f4957612f59565b612f5281612fb5565b9150612f65565b612f6281612ff7565b91505b50919050565b60006000612f80612f7b846129dc565b6129dc565b9050605860020a811015612f9357612fa3565b612f9c81612ff7565b9150612faf565b612fac81612fb5565b91505b50919050565b60006000612fc2836129dc565b9050605960020a811015612fd557612fe5565b612fde81613041565b9150612ff1565b612fee81613083565b91505b50919050565b6000600061300c613007846129dc565b6129dc565b9050605960020a81101561301f5761302f565b61302881613083565b915061303b565b61303881613041565b91505b50919050565b6000600061304e836129dc565b9050605a60020a81101561306157613071565b61306a816130cd565b915061307d565b61307a8161310f565b91505b50919050565b60006000613098613093846129dc565b6129dc565b9050605a60020a8110156130ab576130bb565b6130b48161310f565b91506130c7565b6130c4816130cd565b91505b50919050565b600060006130da836129dc565b9050605b60020a8110156130ed576130fd565b6130f681613159565b9150613109565b6131068161319b565b91505b50919050565b6000600061312461311f846129dc565b6129dc565b9050605b60020a81101561313757613147565b6131408161319b565b9150613153565b61315081613159565b91505b50919050565b60006000613166836129dc565b9050605c60020a81101561317957613189565b613182816131e5565b9150613195565b6131928161196a565b91505b50919050565b600060006131b06131ab846129dc565b6129dc565b9050605c60020a8110156131c3576131d3565b6131cc8161196a565b91506131df565b6131dc816131e5565b91505b50919050565b600060006131f2836129dc565b9050605d60020a81101561320557613215565b61320e816119b4565b9150613221565b61321e816119f6565b91505b50919050565b60006000613234836129dc565b9050607b60020a81101561324757613257565b613250816132b3565b9150613263565b613260816132f5565b91505b50919050565b6000600061327e613279846129dc565b6129dc565b9050607b60020a811015613291576132a1565b61329a816132f5565b91506132ad565b6132aa816132b3565b91505b50919050565b600060006132c0836129dc565b9050607c60020a8110156132d3576132e3565b6132dc8161333f565b91506132ef565b6132ec81613381565b91505b50919050565b6000600061330a613305846129dc565b6129dc565b9050607c60020a81101561331d5761332d565b61332681613381565b9150613339565b6133368161333f565b91505b50919050565b6000600061334c836129dc565b9050607d60020a81101561335f5761336f565b613368816133cb565b915061337b565b6133788161340d565b91505b50919050565b60006000613396613391846129dc565b6129dc565b9050607d60020a8110156133a9576133b9565b6133b28161340d565b91506133c5565b6133c2816133cb565b91505b50919050565b600060006133d8836129dc565b9050607e60020a8110156133eb576133fb565b6133f481613457565b9150613407565b61340481613499565b91505b50919050565b6000600061342261341d846129dc565b6129dc565b9050607e60020a81101561343557613445565b61343e81613499565b9150613451565b61344e81613457565b91505b50919050565b60006000613464836129dc565b9050607f60020a81101561347757613487565b613480816134e3565b9150613493565b61349081613525565b91505b50919050565b600060006134ae6134a9846129dc565b6129dc565b9050607f60020a8110156134c1576134d1565b6134ca81613525565b91506134dd565b6134da816134e3565b91505b50919050565b600060006134f0836129dc565b9050608060020a81101561350357613513565b61350c8161356f565b915061351f565b61351c816135b1565b91505b50919050565b6000600061353a613535846129dc565b6129dc565b9050608060020a81101561354d5761355d565b613556816135b1565b9150613569565b6135668161356f565b91505b50919050565b6000600061357c836129dc565b9050608160020a81101561358f5761359f565b613598816135fb565b91506135ab565b6135a88161363d565b91505b50919050565b600060006135c66135c1846129dc565b6129dc565b9050608160020a8110156135d9576135e9565b6135e28161363d565b91506135f5565b6135f2816135fb565b91505b50919050565b60006000613608836129dc565b9050608260020a81101561361b5761362b565b61362481613687565b9150613637565b613634816136c9565b91505b50919050565b6000600061365261364d846129dc565b6129dc565b9050608260020a81101561366557613675565b61366e816136c9565b9150613681565b61367e81613687565b91505b50919050565b60006000613694836129dc565b9050608360020a8110156136a7576136b7565b6136b081613713565b91506136c3565b6136c081613755565b91505b50919050565b600060006136de6136d9846129dc565b6129dc565b9050608360020a8110156136f157613701565b6136fa81613755565b915061370d565b61370a81613713565b91505b50919050565b60006000613720836129dc565b9050608460020a81101561373357613743565b61373c8161379f565b915061374f565b61374c816137e1565b91505b50919050565b6000600061376a613765846129dc565b6129dc565b9050608460020a81101561377d5761378d565b613786816137e1565b9150613799565b6137968161379f565b91505b50919050565b600060006137ac836129dc565b9050608560020a8110156137bf576137cf565b6137c88161382b565b91506137db565b6137d88161386d565b91505b50919050565b600060006137f66137f1846129dc565b6129dc565b9050608560020a81101561380957613819565b6138128161386d565b9150613825565b6138228161382b565b91505b50919050565b60006000613838836129dc565b9050608660020a81101561384b5761385b565b613854816138b7565b9150613867565b613864816138f9565b91505b50919050565b6000600061388261387d846129dc565b6129dc565b9050608660020a811015613895576138a5565b61389e816138f9565b91506138b1565b6138ae816138b7565b91505b50919050565b600060006138c4836129dc565b9050608760020a8110156138d7576138e7565b6138e081613943565b91506138f3565b6138f081613985565b91505b50919050565b6000600061390e613909846129dc565b6129dc565b9050608760020a81101561392157613931565b61392a81613985565b915061393d565b61393a81613943565b91505b50919050565b60006000613950836129dc565b9050608860020a81101561396357613973565b61396c816139cf565b915061397f565b61397c81613a11565b91505b50919050565b6000600061399a613995846129dc565b6129dc565b9050608860020a8110156139ad576139bd565b6139b681613a11565b91506139c9565b6139c6816139cf565b91505b50919050565b600060006139dc836129dc565b9050608960020a8110156139ef576139ff565b6139f881613a5b565b9150613a0b565b613a0881613a9d565b91505b50919050565b60006000613a26613a21846129dc565b6129dc565b9050608960020a811015613a3957613a49565b613a4281613a9d565b9150613a55565b613a5281613a5b565b91505b50919050565b60006000613a68836129dc565b9050608a60020a811015613a7b57613a8b565b613a8481613ae7565b9150613a97565b613a9481613b29565b91505b50919050565b60006000613ab2613aad846129dc565b6129dc565b9050608a60020a811015613ac557613ad5565b613ace81613b29565b9150613ae1565b613ade81613ae7565b91505b50919050565b60006000613af4836129dc565b9050608b60020a811015613b0757613b17565b613b1081613b73565b9150613b23565b613b2081613bb5565b91505b50919050565b60006000613b3e613b39846129dc565b6129dc565b9050608b60020a811015613b5157613b61565b613b5a81613bb5565b9150613b6d565b613b6a81613b73565b91505b50919050565b60006000613b80836129dc565b9050608c60020a811015613b9357613ba3565b613b9c81613bff565b9150613baf565b613bac81613c41565b91505b50919050565b60006000613bca613bc5846129dc565b6129dc565b9050608c60020a811015613bdd57613bed565b613be681613c41565b9150613bf9565b613bf681613bff565b91505b50919050565b60006000613c0c836129dc565b9050608d60020a811015613c1f57613c2f565b613c2881613c8b565b9150613c3b565b613c3881613ccd565b91505b50919050565b60006000613c56613c51846129dc565b6129dc565b9050608d60020a811015613c6957613c79565b613c7281613ccd565b9150613c85565b613c8281613c8b565b91505b50919050565b60006000613c98836129dc565b9050608e60020a811015613cab57613cbb565b613cb481613d17565b9150613cc7565b613cc481613d59565b91505b50919050565b60006000613ce2613cdd846129dc565b6129dc565b9050608e60020a811015613cf557613d05565b613cfe81613d59565b9150613d11565b613d0e81613d17565b91505b50919050565b60006000613d24836129dc565b9050608f60020a811015613d3757613d47565b613d4081613da3565b9150613d53565b613d5081613de5565b91505b50919050565b60006000613d6e613d69846129dc565b6129dc565b9050608f60020a811015613d8157613d91565b613d8a81613de5565b9150613d9d565b613d9a81613da3565b91505b50919050565b60006000613db0836129dc565b9050609060020a811015613dc357613dd3565b613dcc81613e2f565b9150613ddf565b613ddc81613e71565b91505b50919050565b60006000613dfa613df5846129dc565b6129dc565b9050609060020a811015613e0d57613e1d565b613e1681613e71565b9150613e29565b613e2681613e2f565b91505b50919050565b60006000613e3c836129dc565b9050609160020a811015613e4f57613e5f565b613e5881613ebb565b9150613e6b565b613e6881613efd565b91505b50919050565b60006000613e86613e81846129dc565b6129dc565b9050609160020a811015613e9957613ea9565b613ea281613efd565b9150613eb5565b613eb281613ebb565b91505b50919050565b60006000613ec8836129dc565b9050609260020a811015613edb57613eeb565b613ee481613f47565b9150613ef7565b613ef481613f89565b91505b50919050565b60006000613f12613f0d846129dc565b6129dc565b9050609260020a811015613f2557613f35565b613f2e81613f89565b9150613f41565b613f3e81613f47565b91505b50919050565b60006000613f54836129dc565b9050609360020a811015613f6757613f77565b613f7081613fd3565b9150613f83565b613f8081614015565b91505b50919050565b60006000613f9e613f99846129dc565b6129dc565b9050609360020a811015613fb157613fc1565b613fba81614015565b9150613fcd565b613fca81613fd3565b91505b50919050565b60006000613fe0836129dc565b9050609460020a811015613ff357614003565b613ffc8161405f565b915061400f565b61400c816140a1565b91505b50919050565b6000600061402a614025846129dc565b6129dc565b9050609460020a81101561403d5761404d565b614046816140a1565b9150614059565b6140568161405f565b91505b50919050565b6000600061406c836129dc565b9050609560020a81101561407f5761408f565b614088816140eb565b915061409b565b6140988161412d565b91505b50919050565b600060006140b66140b1846129dc565b6129dc565b9050609560020a8110156140c9576140d9565b6140d28161412d565b91506140e5565b6140e2816140eb565b91505b50919050565b600060006140f8836129dc565b9050609660020a81101561410b5761411b565b61411481614177565b9150614127565b614124816141b9565b91505b50919050565b6000600061414261413d846129dc565b6129dc565b9050609660020a81101561415557614165565b61415e816141b9565b9150614171565b61416e81614177565b91505b50919050565b60006000614184836129dc565b9050609760020a811015614197576141a7565b6141a081614203565b91506141b3565b6141b081614245565b91505b50919050565b600060006141ce6141c9846129dc565b6129dc565b9050609760020a8110156141e1576141f1565b6141ea81614245565b91506141fd565b6141fa81614203565b91505b50919050565b60006000614210836129dc565b9050609860020a81101561422357614233565b61422c8161428f565b915061423f565b61423c816142d1565b91505b50919050565b6000600061425a614255846129dc565b6129dc565b9050609860020a81101561426d5761427d565b614276816142d1565b9150614289565b6142868161428f565b91505b50919050565b6000600061429c836129dc565b9050609960020a8110156142af576142bf565b6142b88161431b565b91506142cb565b6142c88161435d565b91505b50919050565b600060006142e66142e1846129dc565b6129dc565b9050609960020a8110156142f957614309565b6143028161435d565b9150614315565b6143128161431b565b91505b50919050565b60006000614328836129dc565b9050609a60020a81101561433b5761434b565b614344816143a7565b9150614357565b614354816143e9565b91505b50919050565b6000600061437261436d846129dc565b6129dc565b9050609a60020a81101561438557614395565b61438e816143e9565b91506143a1565b61439e816143a7565b91505b50919050565b600060006143b4836129dc565b9050609b60020a8110156143c7576143d7565b6143d081614433565b91506143e3565b6143e081614475565b91505b50919050565b600060006143fe6143f9846129dc565b6129dc565b9050609b60020a81101561441157614421565b61441a81614475565b915061442d565b61442a81614433565b91505b50919050565b60006000614440836129dc565b9050609c60020a81101561445357614463565b61445c816144bf565b915061446f565b61446c81614501565b91505b50919050565b6000600061448a614485846129dc565b6129dc565b9050609c60020a81101561449d576144ad565b6144a681614501565b91506144b9565b6144b6816144bf565b91505b50919050565b600060006144cc836129dc565b9050609d60020a8110156144df576144ef565b6144e88161454b565b91506144fb565b6144f88161458d565b91505b50919050565b60006000614516614511846129dc565b6129dc565b9050609d60020a81101561452957614539565b6145328161458d565b9150614545565b6145428161454b565b91505b50919050565b60006000614558836129dc565b9050609e60020a81101561456b5761457b565b614574816145d7565b9150614587565b61458481614619565b91505b50919050565b600060006145a261459d846129dc565b6129dc565b9050609e60020a8110156145b5576145c5565b6145be81614619565b91506145d1565b6145ce816145d7565b91505b50919050565b600060006145e4836129dc565b9050609f60020a8110156145f757614607565b61460081614663565b9150614613565b614610816146a5565b91505b50919050565b6000600061462e614629846129dc565b6129dc565b9050609f60020a81101561464157614651565b61464a816146a5565b915061465d565b61465a81614663565b91505b50919050565b60006000614670836129dc565b905060a060020a81101561468357614693565b61468c816146ef565b915061469f565b61469c81614731565b91505b50919050565b600060006146ba6146b5846129dc565b6129dc565b905060a060020a8110156146cd576146dd565b6146d681614731565b91506146e9565b6146e6816146ef565b91505b50919050565b600060006146fc836129dc565b905060a160020a81101561470f5761471f565b6147188161477b565b915061472b565b614728816147bd565b91505b50919050565b60006000614746614741846129dc565b6129dc565b905060a160020a81101561475957614769565b614762816147bd565b9150614775565b6147728161477b565b91505b50919050565b60006000614788836129dc565b905060a260020a81101561479b576147ab565b6147a481614807565b91506147b7565b6147b481614849565b91505b50919050565b600060006147d26147cd846129dc565b6129dc565b905060a260020a8110156147e5576147f5565b6147ee81614849565b9150614801565b6147fe81614807565b91505b50919050565b60006000614814836129dc565b905060a360020a81101561482757614837565b61483081614893565b9150614843565b614840816148d5565b91505b50919050565b6000600061485e614859846129dc565b6129dc565b905060a360020a81101561487157614881565b61487a816148d5565b915061488d565b61488a81614893565b91505b50919050565b600060006148a0836129dc565b905060a460020a8110156148b3576148c3565b6148bc8161491f565b91506148cf565b6148cc81614961565b91505b50919050565b600060006148ea6148e5846129dc565b6129dc565b905060a460020a8110156148fd5761490d565b61490681614961565b9150614919565b6149168161491f565b91505b50919050565b6000600061492c836129dc565b905060a560020a81101561493f5761494f565b614948816149ab565b915061495b565b614958816149ed565b91505b50919050565b60006000614976614971846129dc565b6129dc565b905060a560020a81101561498957614999565b614992816149ed565b91506149a5565b6149a2816149ab565b91505b50919050565b600060006149b8836129dc565b905060a660020a8110156149cb576149db565b6149d481614a37565b91506149e7565b6149e481614a79565b91505b50919050565b60006000614a026149fd846129dc565b6129dc565b905060a660020a811015614a1557614a25565b614a1e81614a79565b9150614a31565b614a2e81614a37565b91505b50919050565b60006000614a44836129dc565b905060a760020a811015614a5757614a67565b614a6081614ac3565b9150614a73565b614a7081614b05565b91505b50919050565b60006000614a8e614a89846129dc565b6129dc565b905060a760020a811015614aa157614ab1565b614aaa81614b05565b9150614abd565b614aba81614ac3565b91505b50919050565b60006000614ad0836129dc565b905060a860020a811015614ae357614af3565b614aec81614b4f565b9150614aff565b614afc81614b91565b91505b50919050565b60006000614b1a614b15846129dc565b6129dc565b905060a860020a811015614b2d57614b3d565b614b3681614b91565b9150614b49565b614b4681614b4f565b91505b50919050565b60006000614b5c836129dc565b905060a960020a811015614b6f57614b7f565b614b7881614bdb565b9150614b8b565b614b8881614c1d565b91505b50919050565b60006000614ba6614ba1846129dc565b6129dc565b905060a960020a811015614bb957614bc9565b614bc281614c1d565b9150614bd5565b614bd281614bdb565b91505b50919050565b60006000614be8836129dc565b905060aa60020a811015614bfb57614c0b565b614c0481614c67565b9150614c17565b614c1481614ca9565b91505b50919050565b60006000614c32614c2d846129dc565b6129dc565b905060aa60020a811015614c4557614c55565b614c4e81614ca9565b9150614c61565b614c5e81614c67565b91505b50919050565b60006000614c74836129dc565b905060ab60020a811015614c8757614c97565b614c9081614cf3565b9150614ca3565b614ca081614d35565b91505b50919050565b60006000614cbe614cb9846129dc565b6129dc565b905060ab60020a811015614cd157614ce1565b614cda81614d35565b9150614ced565b614cea81614cf3565b91505b50919050565b60006000614d00836129dc565b905060ac60020a811015614d1357614d23565b614d1c81614d7f565b9150614d2f565b614d2c81614dc1565b91505b50919050565b60006000614d4a614d45846129dc565b6129dc565b905060ac60020a811015614d5d57614d6d565b614d6681614dc1565b9150614d79565b614d7681614d7f565b91505b50919050565b60006000614d8c836129dc565b905060ad60020a811015614d9f57614daf565b614da881614e0b565b9150614dbb565b614db881614e4d565b91505b50919050565b60006000614dd6614dd1846129dc565b6129dc565b905060ad60020a811015614de957614df9565b614df281614e4d565b9150614e05565b614e0281614e0b565b91505b50919050565b60006000614e18836129dc565b905060ae60020a811015614e2b57614e3b565b614e3481614e97565b9150614e47565b614e4481614ed9565b91505b50919050565b60006000614e62614e5d846129dc565b6129dc565b905060ae60020a811015614e7557614e85565b614e7e81614ed9565b9150614e91565b614e8e81614e97565b91505b50919050565b60006000614ea4836129dc565b905060af60020a811015614eb757614ec7565b614ec081614f23565b9150614ed3565b614ed081614f65565b91505b50919050565b60006000614eee614ee9846129dc565b6129dc565b905060af60020a811015614f0157614f11565b614f0a81614f65565b9150614f1d565b614f1a81614f23565b91505b50919050565b60006000614f30836129dc565b905060b060020a811015614f4357614f53565b614f4c81614faf565b9150614f5f565b614f5c81614ff1565b91505b50919050565b60006000614f7a614f75846129dc565b6129dc565b905060b060020a811015614f8d57614f9d565b614f9681614ff1565b9150614fa9565b614fa681614faf565b91505b50919050565b60006000614fbc836129dc565b905060b160020a811015614fcf57614fdf565b614fd881612a11565b9150614feb565b614fe881612a23565b91505b50919050565b60006000615006615001846129dc565b6129dc565b905060b160020a81101561501957615029565b61502281612a23565b9150615035565b61503281612a11565b91505b5091905056", + "storage": {} + } + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", + "value" : "1000000000000000000", + "//" : "ManyFunctions.start(1)", + "data" : "0x95805DAD0000000000000000000000000000000000000000000000000000000000000001", + "gasPrice" : "100000000000000", + "gas" : "10000" + } + }, "ackermann31": { "env" : { "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", diff --git a/test/webthreestubclient.h b/test/webthreestubclient.h index 02f5b5e40..ee175b058 100644 --- a/test/webthreestubclient.h +++ b/test/webthreestubclient.h @@ -183,6 +183,46 @@ class WebThreeStubClient : public jsonrpc::Client else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } + double eth_transactionCountByHash(const std::string& param1) throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p.append(param1); + Json::Value result = this->CallMethod("eth_transactionCountByHash",p); + if (result.isDouble()) + return result.asDouble(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + } + double eth_transactionCountByNumber(int param1) throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p.append(param1); + Json::Value result = this->CallMethod("eth_transactionCountByNumber",p); + if (result.isDouble()) + return result.asDouble(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + } + double eth_uncleCountByHash(const std::string& param1) throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p.append(param1); + Json::Value result = this->CallMethod("eth_uncleCountByHash",p); + if (result.isDouble()) + return result.asDouble(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + } + double eth_uncleCountByNumber(int param1) throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p.append(param1); + Json::Value result = this->CallMethod("eth_uncleCountByNumber",p); + if (result.isDouble()) + return result.asDouble(); + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + } std::string eth_codeAt(const std::string& param1) throw (jsonrpc::JsonRpcException) { Json::Value p; @@ -535,6 +575,16 @@ class WebThreeStubClient : public jsonrpc::Client else throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); } + Json::Value shh_getMessages(int param1) throw (jsonrpc::JsonRpcException) + { + Json::Value p; + p.append(param1); + Json::Value result = this->CallMethod("shh_getMessages",p); + if (result.isArray()) + return result; + else + throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); + } }; #endif //JSONRPC_CPP_STUB_WEBTHREESTUBCLIENT_H_ diff --git a/third/CMakeLists.txt b/third/CMakeLists.txt index 3f4981e29..bde47988b 100644 --- a/third/CMakeLists.txt +++ b/third/CMakeLists.txt @@ -10,8 +10,8 @@ endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(. SRC_LIST) +include_directories(BEFORE ..) include_directories(${JSON_RPC_CPP_INCLUDE_DIRS}) -include_directories(..) qt5_wrap_ui(ui_Main.h Main.ui)