From c2b194d4c35bdbb2e8b2cda948af1556ed969bdc Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 6 Jan 2015 17:42:38 +0100 Subject: [PATCH 1/4] Creating the canonical signature of a function, for later use in the ABI --- libsolidity/AST.cpp | 17 +++++++++++++++++ libsolidity/AST.h | 6 ++++++ 2 files changed, 23 insertions(+) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 1fa6d8f6f..629525210 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -110,6 +110,23 @@ void FunctionDefinition::checkTypeRequirements() m_body->checkTypeRequirements(); } +std::string FunctionDefinition::getCanonicalSignature() +{ + auto parameters = getParameters(); + std::string ret = getName() + "("; + unsigned int i = 1; + + for (ASTPointer const& member: parameters) + { + ret += member->getType()->toString(); + if (i != parameters.size()) { + ret += ","; + } + } + ret += ")"; + return ret; +} + void Block::checkTypeRequirements() { for (shared_ptr const& statement: m_statements) diff --git a/libsolidity/AST.h b/libsolidity/AST.h index b7c3dc6c0..32cc23a5b 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -277,6 +277,12 @@ public: /// Checks that all parameters have allowed types and calls checkTypeRequirements on the body. void checkTypeRequirements(); + /// Returns the canonical signature of the function + /// That consists of the name of the function followed by the + /// types of the arguments separated by commas all enclosed in parentheses + /// without any spaces + std::string getCanonicalSignature(); + private: bool m_isPublic; ASTPointer m_parameters; From 0c83932d911eccc61383990f0e1da1e5ecad5531 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 7 Jan 2015 02:07:34 +0100 Subject: [PATCH 2/4] Test for the Canonical Signature of a function --- libsolidity/AST.cpp | 1 + test/SolidityNameAndTypeResolution.cpp | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 629525210..fd8f45a73 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -122,6 +122,7 @@ std::string FunctionDefinition::getCanonicalSignature() if (i != parameters.size()) { ret += ","; } + i++; } ret += ")"; return ret; diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index 25bff71f7..e44c9fa29 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -38,7 +38,7 @@ namespace test namespace { -void parseTextAndResolveNames(std::string const& _source) +ASTPointer parseTextAndResolveNames(std::string const& _source) { Parser parser; ASTPointer sourceUnit = parser.parse(std::make_shared(CharStream(_source))); @@ -50,6 +50,8 @@ void parseTextAndResolveNames(std::string const& _source) for (ASTPointer const& node: sourceUnit->getNodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) resolver.checkTypeRequirements(*contract); + + return sourceUnit; } } @@ -321,6 +323,23 @@ BOOST_AUTO_TEST_CASE(comparison_bitop_precedence) BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); } +BOOST_AUTO_TEST_CASE(function_canonical_signature) +{ + ASTPointer sourceUnit; + char const* text = "contract Test {\n" + " function foo(uint256 arg1, uint64 arg2, bool arg3) returns (uint256 ret) {\n" + " ret = arg1 + arg2;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(sourceUnit = parseTextAndResolveNames(text)); + for (ASTPointer const& node: sourceUnit->getNodes()) + if (ContractDefinition* contract = dynamic_cast(node.get())) + { + auto functions = contract->getDefinedFunctions(); + BOOST_ASSERT("foo(uint256,uint64,bool)" == functions[0]->getCanonicalSignature()); + } +} + BOOST_AUTO_TEST_SUITE_END() } From 0c003958b942e3cfbd0023b61939c0b0fde5e5bd Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 7 Jan 2015 02:27:05 +0100 Subject: [PATCH 3/4] FunctionType also gets CanonicalSignature - also using iterators in the signature creation function --- libsolidity/AST.cpp | 14 +++----------- libsolidity/Types.cpp | 11 +++++++++++ libsolidity/Types.h | 1 + 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index fd8f45a73..cdbfb4e9a 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -114,18 +114,10 @@ std::string FunctionDefinition::getCanonicalSignature() { auto parameters = getParameters(); std::string ret = getName() + "("; - unsigned int i = 1; - for (ASTPointer const& member: parameters) - { - ret += member->getType()->toString(); - if (i != parameters.size()) { - ret += ","; - } - i++; - } - ret += ")"; - return ret; + for (auto it = parameters.cbegin(); it != parameters.cend(); ++it) + ret += (*it)->getType()->toString() + (it + 1 == parameters.end() ? "" : ","); + return ret + ")"; } void Block::checkTypeRequirements() diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 71319c3ac..640a34ca8 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -452,6 +452,17 @@ unsigned FunctionType::getSizeOnStack() const } } +std::string FunctionType::getCanonicalSignature() const +{ + auto parameters = getParameterTypes(); + std::string ret = "NAME("; //TODO: how to get function name from FunctionType + + for (auto it = parameters.cbegin(); it != parameters.cend(); ++it) + ret += (*it)->toString() + (it + 1 == m_parameterTypes.end() ? "" : ","); + + return ret + ")"; +} + bool MappingType::operator==(Type const& _other) const { if (_other.getCategory() != getCategory()) diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 48539a1d7..0fe685b87 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -325,6 +325,7 @@ public: virtual unsigned getSizeOnStack() const override; Location const& getLocation() const { return m_location; } + std::string getCanonicalSignature() const; private: TypePointers m_parameterTypes; From 48080e041500135cf0379724f769a04e881d2dce Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 7 Jan 2015 10:45:59 +0100 Subject: [PATCH 4/4] Small issues with Canonical Function Signature - Also added an extra test --- libsolidity/AST.cpp | 9 ++------- libsolidity/AST.h | 9 ++++----- libsolidity/Types.cpp | 9 ++++----- test/SolidityNameAndTypeResolution.cpp | 19 ++++++++++++++++++- 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index cdbfb4e9a..0c56cb7a7 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -110,14 +110,9 @@ void FunctionDefinition::checkTypeRequirements() m_body->checkTypeRequirements(); } -std::string FunctionDefinition::getCanonicalSignature() +string FunctionDefinition::getCanonicalSignature() const { - auto parameters = getParameters(); - std::string ret = getName() + "("; - - for (auto it = parameters.cbegin(); it != parameters.cend(); ++it) - ret += (*it)->getType()->toString() + (it + 1 == parameters.end() ? "" : ","); - return ret + ")"; + return getName() + FunctionType(*this).getCanonicalSignature(); } void Block::checkTypeRequirements() diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 32cc23a5b..8493d4323 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -277,11 +277,10 @@ public: /// Checks that all parameters have allowed types and calls checkTypeRequirements on the body. void checkTypeRequirements(); - /// Returns the canonical signature of the function - /// That consists of the name of the function followed by the - /// types of the arguments separated by commas all enclosed in parentheses - /// without any spaces - std::string getCanonicalSignature(); + /// @returns the canonical signature of the function + /// That consists of the name of the function followed by the types of the + /// arguments separated by commas all enclosed in parentheses without any spaces. + std::string getCanonicalSignature() const; private: bool m_isPublic; diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 640a34ca8..7a4c45c6f 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -452,13 +452,12 @@ unsigned FunctionType::getSizeOnStack() const } } -std::string FunctionType::getCanonicalSignature() const +string FunctionType::getCanonicalSignature() const { - auto parameters = getParameterTypes(); - std::string ret = "NAME("; //TODO: how to get function name from FunctionType + string ret = "("; - for (auto it = parameters.cbegin(); it != parameters.cend(); ++it) - ret += (*it)->toString() + (it + 1 == m_parameterTypes.end() ? "" : ","); + for (auto it = m_parameterTypes.cbegin(); it != m_parameterTypes.cend(); ++it) + ret += (*it)->toString() + (it + 1 == m_parameterTypes.cend() ? "" : ","); return ret + ")"; } diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index e44c9fa29..94271b1f7 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -336,7 +336,24 @@ BOOST_AUTO_TEST_CASE(function_canonical_signature) if (ContractDefinition* contract = dynamic_cast(node.get())) { auto functions = contract->getDefinedFunctions(); - BOOST_ASSERT("foo(uint256,uint64,bool)" == functions[0]->getCanonicalSignature()); + BOOST_CHECK_EQUAL("foo(uint256,uint64,bool)", functions[0]->getCanonicalSignature()); + } +} + +BOOST_AUTO_TEST_CASE(function_canonical_signature_type_aliases) +{ + ASTPointer sourceUnit; + char const* text = "contract Test {\n" + " function boo(uint arg1, hash arg2, address arg3) returns (uint ret) {\n" + " ret = 5;\n" + " }\n" + "}\n"; + BOOST_CHECK_NO_THROW(sourceUnit = parseTextAndResolveNames(text)); + for (ASTPointer const& node: sourceUnit->getNodes()) + if (ContractDefinition* contract = dynamic_cast(node.get())) + { + auto functions = contract->getDefinedFunctions(); + BOOST_CHECK_EQUAL("boo(uint256,hash256,address)", functions[0]->getCanonicalSignature()); } }