From ffce12b7ee412cbd29dd0873a3e894dd7133ca4e Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 9 Jan 2015 00:22:06 +0100 Subject: [PATCH] Basic logging in Solidity (though no tests yet). --- CompilerStack.cpp | 8 ++++++ CompilerStack.h | 7 +++++- ExpressionCompiler.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++ GlobalContext.cpp | 55 +++++++++++++++++++++++++++++------------- InterfaceHandler.cpp | 25 +++++++++++++++++++ InterfaceHandler.h | 1 + Types.h | 2 +- 7 files changed, 134 insertions(+), 19 deletions(-) diff --git a/CompilerStack.cpp b/CompilerStack.cpp index 79716fdec..1c883a7f6 100644 --- a/CompilerStack.cpp +++ b/CompilerStack.cpp @@ -143,6 +143,11 @@ string const& CompilerStack::getInterface(string const& _contractName) const return getJsonDocumentation(_contractName, DocumentationType::ABI_INTERFACE); } +string const& CompilerStack::getSolidityInterface(string const& _contractName) const +{ + return getJsonDocumentation(_contractName, DocumentationType::ABI_SOLIDITY_INTERFACE); +} + string const& CompilerStack::getJsonDocumentation(string const& _contractName, DocumentationType _type) const { if (!m_parseSuccessful) @@ -162,6 +167,9 @@ string const& CompilerStack::getJsonDocumentation(string const& _contractName, D case DocumentationType::ABI_INTERFACE: doc = &contract.interface; break; + case DocumentationType::ABI_SOLIDITY_INTERFACE: + doc = &contract.solidityInterface; + break; default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Illegal documentation type.")); } diff --git a/CompilerStack.h b/CompilerStack.h index e7143b7bb..d6378ea1e 100644 --- a/CompilerStack.h +++ b/CompilerStack.h @@ -43,7 +43,8 @@ enum class DocumentationType: uint8_t { NATSPEC_USER = 1, NATSPEC_DEV, - ABI_INTERFACE + ABI_INTERFACE, + ABI_SOLIDITY_INTERFACE }; /** @@ -81,6 +82,9 @@ public: /// Returns a string representing the contract interface in JSON. /// Prerequisite: Successful call to parse or compile. std::string const& getInterface(std::string const& _contractName = "") const; + /// Returns a string representing the contract interface in JSON. + /// Prerequisite: Successful call to parse or compile. + std::string const& getSolidityInterface(std::string const& _contractName = "") const; /// Returns a string representing the contract's documentation in JSON. /// Prerequisite: Successful call to parse or compile. /// @param type The type of the documentation to get. @@ -118,6 +122,7 @@ private: bytes bytecode; std::shared_ptr interfaceHandler; mutable std::unique_ptr interface; + mutable std::unique_ptr solidityInterface; mutable std::unique_ptr userDocumentation; mutable std::unique_ptr devDocumentation; diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index aa7406132..ec66b69af 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -256,6 +256,61 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) CompilerUtils(m_context).storeInMemory(0); m_context << u256(32) << u256(0) << eth::Instruction::SHA3; break; + case Location::LOG0: + arguments.front()->accept(*this); + appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front(), true); + // @todo move this once we actually use memory + CompilerUtils(m_context).storeInMemory(0); + m_context << u256(32) << u256(0) << eth::Instruction::LOG0; + break; + case Location::LOG1: + arguments[1]->accept(*this); + arguments[0]->accept(*this); + appendTypeConversion(*arguments[1]->getType(), *function.getParameterTypes()[1], true); + appendTypeConversion(*arguments[0]->getType(), *function.getParameterTypes()[0], true); + // @todo move this once we actually use memory + CompilerUtils(m_context).storeInMemory(0); + m_context << u256(32) << u256(0) << eth::Instruction::LOG1; + break; + case Location::LOG2: + arguments[2]->accept(*this); + arguments[1]->accept(*this); + arguments[0]->accept(*this); + appendTypeConversion(*arguments[2]->getType(), *function.getParameterTypes()[2], true); + appendTypeConversion(*arguments[1]->getType(), *function.getParameterTypes()[1], true); + appendTypeConversion(*arguments[0]->getType(), *function.getParameterTypes()[0], true); + // @todo move this once we actually use memory + CompilerUtils(m_context).storeInMemory(0); + m_context << u256(32) << u256(0) << eth::Instruction::LOG2; + break; + case Location::LOG3: + arguments[3]->accept(*this); + arguments[2]->accept(*this); + arguments[1]->accept(*this); + arguments[0]->accept(*this); + appendTypeConversion(*arguments[3]->getType(), *function.getParameterTypes()[3], true); + appendTypeConversion(*arguments[2]->getType(), *function.getParameterTypes()[2], true); + appendTypeConversion(*arguments[1]->getType(), *function.getParameterTypes()[1], true); + appendTypeConversion(*arguments[0]->getType(), *function.getParameterTypes()[0], true); + // @todo move this once we actually use memory + CompilerUtils(m_context).storeInMemory(0); + m_context << u256(32) << u256(0) << eth::Instruction::LOG3; + break; + case Location::LOG4: + arguments[4]->accept(*this); + arguments[3]->accept(*this); + arguments[2]->accept(*this); + arguments[1]->accept(*this); + arguments[0]->accept(*this); + appendTypeConversion(*arguments[4]->getType(), *function.getParameterTypes()[4], true); + appendTypeConversion(*arguments[3]->getType(), *function.getParameterTypes()[3], true); + appendTypeConversion(*arguments[2]->getType(), *function.getParameterTypes()[2], true); + appendTypeConversion(*arguments[1]->getType(), *function.getParameterTypes()[1], true); + appendTypeConversion(*arguments[0]->getType(), *function.getParameterTypes()[0], true); + // @todo move this once we actually use memory + CompilerUtils(m_context).storeInMemory(0); + m_context << u256(32) << u256(0) << eth::Instruction::LOG4; + break; case Location::ECRECOVER: case Location::SHA256: case Location::RIPEMD160: diff --git a/GlobalContext.cpp b/GlobalContext.cpp index f4805b1f7..bf2ed479c 100644 --- a/GlobalContext.cpp +++ b/GlobalContext.cpp @@ -33,33 +33,54 @@ namespace solidity { GlobalContext::GlobalContext(): +// TODO: make this cleaner. m_magicVariables(vector>{make_shared("block", make_shared(MagicType::Kind::BLOCK)), - make_shared("msg", make_shared(MagicType::Kind::MSG)), - make_shared("tx", make_shared(MagicType::Kind::TX)), - make_shared("suicide", + make_shared("msg", make_shared(MagicType::Kind::MSG)), + make_shared("tx", make_shared(MagicType::Kind::TX)), + make_shared("suicide", make_shared(TypePointers({std::make_shared(0, IntegerType::Modifier::ADDRESS)}), - TypePointers(), - FunctionType::Location::SUICIDE)), - make_shared("sha3", + TypePointers(), + FunctionType::Location::SUICIDE)), + make_shared("sha3", make_shared(TypePointers({std::make_shared(256, IntegerType::Modifier::HASH)}), - TypePointers({std::make_shared(256, IntegerType::Modifier::HASH)}), - FunctionType::Location::SHA3)), - make_shared("sha256", + TypePointers({std::make_shared(256, IntegerType::Modifier::HASH)}), + FunctionType::Location::SHA3)), + make_shared("log0", make_shared(TypePointers({std::make_shared(256, IntegerType::Modifier::HASH)}), - TypePointers({std::make_shared(256, IntegerType::Modifier::HASH)}), - FunctionType::Location::SHA256)), - make_shared("ecrecover", + TypePointers(), + FunctionType::Location::LOG0)), + make_shared("log1", + make_shared(TypePointers({std::make_shared(256, IntegerType::Modifier::HASH), std::make_shared(256, IntegerType::Modifier::HASH)}), + TypePointers(), + FunctionType::Location::LOG1)), + make_shared("log2", + make_shared(TypePointers({std::make_shared(256, IntegerType::Modifier::HASH), std::make_shared(256, IntegerType::Modifier::HASH), std::make_shared(256, IntegerType::Modifier::HASH)}), + TypePointers(), + FunctionType::Location::LOG2)), + make_shared("log3", + make_shared(TypePointers({std::make_shared(256, IntegerType::Modifier::HASH), std::make_shared(256, IntegerType::Modifier::HASH), std::make_shared(256, IntegerType::Modifier::HASH), std::make_shared(256, IntegerType::Modifier::HASH)}), + TypePointers(), + FunctionType::Location::LOG3)), + make_shared("log4", + make_shared(TypePointers({std::make_shared(256, IntegerType::Modifier::HASH), std::make_shared(256, IntegerType::Modifier::HASH), std::make_shared(256, IntegerType::Modifier::HASH), std::make_shared(256, IntegerType::Modifier::HASH), std::make_shared(256, IntegerType::Modifier::HASH)}), + TypePointers(), + FunctionType::Location::LOG4)), + make_shared("sha256", + make_shared(TypePointers({std::make_shared(256, IntegerType::Modifier::HASH)}), + TypePointers({std::make_shared(256, IntegerType::Modifier::HASH)}), + FunctionType::Location::SHA256)), + make_shared("ecrecover", make_shared(TypePointers({std::make_shared(256, IntegerType::Modifier::HASH), std::make_shared(8, IntegerType::Modifier::HASH), std::make_shared(256, IntegerType::Modifier::HASH), std::make_shared(256, IntegerType::Modifier::HASH)}), - TypePointers({std::make_shared(0, IntegerType::Modifier::ADDRESS)}), - FunctionType::Location::ECRECOVER)), - make_shared("ripemd160", + TypePointers({std::make_shared(0, IntegerType::Modifier::ADDRESS)}), + FunctionType::Location::ECRECOVER)), + make_shared("ripemd160", make_shared(TypePointers({std::make_shared(256, IntegerType::Modifier::HASH)}), - TypePointers({std::make_shared(160, IntegerType::Modifier::HASH)}), - FunctionType::Location::RIPEMD160))}) + TypePointers({std::make_shared(160, IntegerType::Modifier::HASH)}), + FunctionType::Location::RIPEMD160))}) { } diff --git a/InterfaceHandler.cpp b/InterfaceHandler.cpp index 224234cbd..06b9824c9 100644 --- a/InterfaceHandler.cpp +++ b/InterfaceHandler.cpp @@ -2,6 +2,7 @@ #include #include #include +using namespace std; namespace dev { @@ -26,6 +27,8 @@ std::unique_ptr InterfaceHandler::getDocumentation(ContractDefiniti return getDevDocumentation(_contractDef); case DocumentationType::ABI_INTERFACE: return getABIInterface(_contractDef); + case DocumentationType::ABI_SOLIDITY_INTERFACE: + return getABISolidityInterface(_contractDef); } BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown documentation type")); @@ -64,6 +67,28 @@ std::unique_ptr InterfaceHandler::getABIInterface(ContractDefinitio return std::unique_ptr(new std::string(m_writer.write(methods))); } +unique_ptr InterfaceHandler::getABISolidityInterface(ContractDefinition const& _contractDef) +{ + string ret = "contract " + _contractDef.getName() + "{"; + for (FunctionDefinition const* f: _contractDef.getInterfaceFunctions()) + { + auto populateParameters = [](vector> const& _vars) + { + string r = ""; + for (ASTPointer const& var: _vars) + r += (r.size() ? "," : "(") + var->getType()->toString() + " " + var->getName(); + return r.size() ? r + ")" : "()"; + }; + ret += "function " + f->getName() + populateParameters(f->getParameters()) + (f->isDeclaredConst() ? "constant " : ""); + if (f->getReturnParameters().size()) + ret += "returns" + populateParameters(f->getReturnParameters()); + else if (ret.back() == ' ') + ret.pop_back(); + ret += "{}"; + } + return unique_ptr(new string(ret + "}")); +} + std::unique_ptr InterfaceHandler::getUserDocumentation(ContractDefinition const& _contractDef) { Json::Value doc; diff --git a/InterfaceHandler.h b/InterfaceHandler.h index c8399d71f..2b62cabdf 100644 --- a/InterfaceHandler.h +++ b/InterfaceHandler.h @@ -74,6 +74,7 @@ public: /// @return A unique pointer contained string with the json /// representation of the contract's ABI Interface std::unique_ptr getABIInterface(ContractDefinition const& _contractDef); + std::unique_ptr getABISolidityInterface(ContractDefinition const& _contractDef); /// Get the User documentation of the contract /// @param _contractDef The contract definition /// @return A unique pointer contained string with the json diff --git a/Types.h b/Types.h index a91a6c24e..b25d5d895 100644 --- a/Types.h +++ b/Types.h @@ -318,7 +318,7 @@ public: /// INTERNAL: jump tag, EXTERNAL: contract address + function index, /// BARE: contract address (non-abi contract call) /// OTHERS: special virtual function, nothing on the stack - enum class Location { INTERNAL, EXTERNAL, SEND, SHA3, SUICIDE, ECRECOVER, SHA256, RIPEMD160, BARE }; + enum class Location { INTERNAL, EXTERNAL, SEND, SHA3, SUICIDE, ECRECOVER, SHA256, RIPEMD160, LOG0, LOG1, LOG2, LOG3, LOG4, BARE }; virtual Category getCategory() const override { return Category::FUNCTION; } explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true);