From de531cb2744568a2833f5ef25588a18ae3d3ad30 Mon Sep 17 00:00:00 2001 From: arkpar Date: Sat, 31 Jan 2015 14:41:11 +0100 Subject: [PATCH 1/2] json and solidity ABI generted for events --- libsolidity/AST.cpp | 17 ++++ libsolidity/AST.h | 2 + libsolidity/InterfaceHandler.cpp | 43 +++++++-- test/SolidityABIJSON.cpp | 157 +++++++++++++++++++++++++++++-- 4 files changed, 200 insertions(+), 19 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index d7bfb0d34..10464726e 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -152,6 +152,23 @@ void ContractDefinition::checkIllegalOverrides() const } } +std::vector> const& ContractDefinition::getInterfaceEvents() const +{ + if (!m_interfaceEvents) + { + set eventsSeen; + m_interfaceEvents.reset(new std::vector>()); + for (ContractDefinition const* contract: getLinearizedBaseContracts()) + for (ASTPointer const& e: contract->getEvents()) + if (eventsSeen.count(e->getName()) == 0) + { + eventsSeen.insert(e->getName()); + m_interfaceEvents->push_back(e); + } + } + return *m_interfaceEvents; +} + vector, FunctionTypePointer>> const& ContractDefinition::getInterfaceFunctionList() const { if (!m_interfaceFunctionList) diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 113daf72e..fefd0e947 100755 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -222,6 +222,7 @@ public: std::vector> const& getFunctionModifiers() const { return m_functionModifiers; } std::vector> const& getDefinedFunctions() const { return m_definedFunctions; } std::vector> const& getEvents() const { return m_events; } + std::vector> const& getInterfaceEvents() const; virtual TypePointer getType(ContractDefinition const* m_currentContract) const override; @@ -257,6 +258,7 @@ private: std::vector m_linearizedBaseContracts; mutable std::unique_ptr, FunctionTypePointer>>> m_interfaceFunctionList; + mutable std::unique_ptr>> m_interfaceEvents; }; class InheritanceSpecifier: public ASTNode diff --git a/libsolidity/InterfaceHandler.cpp b/libsolidity/InterfaceHandler.cpp index c4bed99f7..e9c74fb8a 100644 --- a/libsolidity/InterfaceHandler.cpp +++ b/libsolidity/InterfaceHandler.cpp @@ -37,16 +37,11 @@ std::unique_ptr InterfaceHandler::getDocumentation(ContractDefiniti std::unique_ptr InterfaceHandler::getABIInterface(ContractDefinition const& _contractDef) { - Json::Value methods(Json::arrayValue); - + Json::Value abi(Json::arrayValue); for (auto const& it: _contractDef.getInterfaceFunctions()) { Json::Value method; - Json::Value inputs(Json::arrayValue); - Json::Value outputs(Json::arrayValue); - - auto populateParameters = [](vector const& _paramNames, - vector const& _paramTypes) + auto populateParameters = [](vector const& _paramNames, vector const& _paramTypes) { Json::Value params(Json::arrayValue); solAssert(_paramNames.size() == _paramTypes.size(), "Names and types vector size does not match"); @@ -66,9 +61,28 @@ std::unique_ptr InterfaceHandler::getABIInterface(ContractDefinitio it.second->getParameterTypeNames()); method["outputs"] = populateParameters(it.second->getReturnParameterNames(), it.second->getReturnParameterTypeNames()); - methods.append(method); + abi.append(method); + } + + for (auto const& it: _contractDef.getInterfaceEvents()) + { + Json::Value event; + event["type"] = "event"; + event["name"] = it->getName(); + Json::Value params(Json::arrayValue); + for (auto const& p: it->getParameters()) + { + Json::Value input; + input["name"] = p->getName(); + input["type"] = p->getType()->toString(); + input["indexed"] = p->isIndexed(); + params.append(input); + } + event["inputs"] = params; + abi.append(event); } - return std::unique_ptr(new std::string(m_writer.write(methods))); + + return std::unique_ptr(new std::string(m_writer.write(abi))); } unique_ptr InterfaceHandler::getABISolidityInterface(ContractDefinition const& _contractDef) @@ -94,6 +108,17 @@ unique_ptr InterfaceHandler::getABISolidityInterface(ContractDefinition ret.pop_back(); ret += "{}"; } + for (auto const& it: _contractDef.getInterfaceEvents()) + { + std::string params; + for (auto const& p: it->getParameters()) + params += (params.empty() ? "(" : ",") + p->getType()->toString() + (p->isIndexed() ? " indexed " : " ") + p->getName(); + if (!params.empty()) + params += ")"; + + ret += "event " + it->getName() + params + ";"; + } + return unique_ptr(new string(ret + "}")); } diff --git a/test/SolidityABIJSON.cpp b/test/SolidityABIJSON.cpp index aa5fcb0e0..1f7d35ab1 100644 --- a/test/SolidityABIJSON.cpp +++ b/test/SolidityABIJSON.cpp @@ -37,7 +37,7 @@ class InterfaceChecker public: InterfaceChecker(): m_compilerStack(false) {} - void checkInterface(std::string const& _code, std::string const& _expectedInterfaceString) + void checkInterface(std::string const& _code, std::string const& _expectedInterfaceString, std::string const& expectedSolidityInterface) { try { @@ -49,13 +49,17 @@ public: BOOST_FAIL(msg); } std::string generatedInterfaceString = m_compilerStack.getMetadata("", DocumentationType::ABI_INTERFACE); + std::string generatedSolidityInterfaceString = m_compilerStack.getMetadata("", DocumentationType::ABI_SOLIDITY_INTERFACE); Json::Value generatedInterface; m_reader.parse(generatedInterfaceString, generatedInterface); Json::Value expectedInterface; m_reader.parse(_expectedInterfaceString, expectedInterface); BOOST_CHECK_MESSAGE(expectedInterface == generatedInterface, - "Expected " << _expectedInterfaceString << - "\n but got:\n" << generatedInterfaceString); + "Expected:\n" << expectedInterface.toStyledString() << + "\n but got:\n" << generatedInterface.toStyledString()); + BOOST_CHECK_MESSAGE(expectedSolidityInterface == generatedSolidityInterfaceString, + "Expected:\n" << expectedSolidityInterface << + "\n but got:\n" << generatedSolidityInterfaceString); } private: @@ -71,6 +75,8 @@ BOOST_AUTO_TEST_CASE(basic_test) " function f(uint a) returns(uint d) { return a * 7; }\n" "}\n"; + char const* sourceInterface = "contract test{function f(uint256 a)returns(uint256 d){}}"; + char const* interface = R"([ { "name": "f", @@ -91,17 +97,18 @@ BOOST_AUTO_TEST_CASE(basic_test) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, interface, sourceInterface); } BOOST_AUTO_TEST_CASE(empty_contract) { char const* sourceCode = "contract test {\n" "}\n"; + char const* sourceInterface = "contract test{}"; char const* interface = "[]"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, interface, sourceInterface); } BOOST_AUTO_TEST_CASE(multiple_methods) @@ -110,6 +117,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods) " function f(uint a) returns(uint d) { return a * 7; }\n" " function g(uint b) returns(uint e) { return b * 8; }\n" "}\n"; + char const* sourceInterface = "contract test{function f(uint256 a)returns(uint256 d){}function g(uint256 b)returns(uint256 e){}}"; char const* interface = R"([ { @@ -148,7 +156,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, interface, sourceInterface); } BOOST_AUTO_TEST_CASE(multiple_params) @@ -156,6 +164,7 @@ BOOST_AUTO_TEST_CASE(multiple_params) char const* sourceCode = "contract test {\n" " function f(uint a, uint b) returns(uint d) { return a + b; }\n" "}\n"; + char const* sourceInterface = "contract test{function f(uint256 a,uint256 b)returns(uint256 d){}}"; char const* interface = R"([ { @@ -181,7 +190,7 @@ BOOST_AUTO_TEST_CASE(multiple_params) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, interface, sourceInterface); } BOOST_AUTO_TEST_CASE(multiple_methods_order) @@ -191,6 +200,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order) " function f(uint a) returns(uint d) { return a * 7; }\n" " function c(uint b) returns(uint e) { return b * 8; }\n" "}\n"; + char const* sourceInterface = "contract test{function c(uint256 b)returns(uint256 e){}function f(uint256 a)returns(uint256 d){}}"; char const* interface = R"([ { @@ -229,7 +239,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, interface, sourceInterface); } BOOST_AUTO_TEST_CASE(const_function) @@ -238,6 +248,7 @@ BOOST_AUTO_TEST_CASE(const_function) " function foo(uint a, uint b) returns(uint d) { return a + b; }\n" " function boo(uint32 a) constant returns(uint b) { return a * 4; }\n" "}\n"; + char const* sourceInterface = "contract test{function foo(uint256 a,uint256 b)returns(uint256 d){}function boo(uint32 a)constant returns(uint256 b){}}"; char const* interface = R"([ { @@ -278,18 +289,144 @@ BOOST_AUTO_TEST_CASE(const_function) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, interface, sourceInterface); } BOOST_AUTO_TEST_CASE(exclude_fallback_function) { char const* sourceCode = "contract test { function() {} }"; + char const* sourceInterface = "contract test{}"; char const* interface = "[]"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, interface, sourceInterface); +} + +BOOST_AUTO_TEST_CASE(events) +{ + char const* sourceCode = "contract test {\n" + " function f(uint a) returns(uint d) { return a * 7; }\n" + " event e1(uint b, address indexed c); \n" + " event e2(); \n" + "}\n"; + char const* sourceInterface = "contract test{function f(uint256 a)returns(uint256 d){}event e1(uint256 b,address indexed c);event e2;}"; + + char const* interface = R"([ + { + "name": "f", + "constant": false, + "type": "function", + "inputs": [ + { + "name": "a", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "d", + "type": "uint256" + } + ] + }, + { + "name": "e1", + "type": "event", + "inputs": [ + { + "indexed": false, + "name": "b", + "type": "uint256" + }, + { + "indexed": true, + "name": "c", + "type": "address" + } + ] + }, + { + "name": "e2", + "type": "event", + "inputs": [] + } + + ])"; + + checkInterface(sourceCode, interface, sourceInterface); +} + + +BOOST_AUTO_TEST_CASE(inherited) +{ + char const* sourceCode = + " contract Base { \n" + " function baseFunction(uint p) returns (uint i) { return p; } \n" + " event baseEvent(string32 indexed evtArgBase); \n" + " } \n" + " contract Derived is Base { \n" + " function derivedFunction(string32 p) returns (string32 i) { return p; } \n" + " event derivedEvent(uint indexed evtArgDerived); \n" + " }"; + char const* sourceInterface = "contract Derived{function baseFunction(uint256 p)returns(uint256 i){}function derivedFunction(string32 p)returns(string32 i){}event derivedEvent(uint256 indexed evtArgDerived);event baseEvent(string32 indexed evtArgBase);}"; + + char const* interface = R"([ + { + "name": "baseFunction", + "constant": false, + "type": "function", + "inputs": + [{ + "name": "p", + "type": "uint256" + }], + "outputs": + [{ + "name": "i", + "type": "uint256" + }] + }, + { + "name": "derivedFunction", + "constant": false, + "type": "function", + "inputs": + [{ + "name": "p", + "type": "string32" + }], + "outputs": + [{ + "name": "i", + "type": "string32" + }] + }, + { + "name": "derivedEvent", + "type": "event", + "inputs": + [{ + "indexed": true, + "name": "evtArgDerived", + "type": "uint256" + }] + }, + { + "name": "baseEvent", + "type": "event", + "inputs": + [{ + "indexed": true, + "name": "evtArgBase", + "type": "string32" + }] + }])"; + + + checkInterface(sourceCode, interface, sourceInterface); } + BOOST_AUTO_TEST_SUITE_END() } From 2677a6ea9029c4c9bc2651df6543ac02770d3221 Mon Sep 17 00:00:00 2001 From: arkpar Date: Sat, 31 Jan 2015 14:44:04 +0100 Subject: [PATCH 2/2] style --- libsolidity/InterfaceHandler.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libsolidity/InterfaceHandler.cpp b/libsolidity/InterfaceHandler.cpp index e9c74fb8a..7d0598eda 100644 --- a/libsolidity/InterfaceHandler.cpp +++ b/libsolidity/InterfaceHandler.cpp @@ -81,7 +81,6 @@ std::unique_ptr InterfaceHandler::getABIInterface(ContractDefinitio event["inputs"] = params; abi.append(event); } - return std::unique_ptr(new std::string(m_writer.write(abi))); } @@ -118,7 +117,6 @@ unique_ptr InterfaceHandler::getABISolidityInterface(ContractDefinition ret += "event " + it->getName() + params + ";"; } - return unique_ptr(new string(ret + "}")); }