Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add .selector member on function types #2473

Merged
merged 5 commits into from
Sep 13, 2017
Merged

Add .selector member on function types #2473

merged 5 commits into from
Sep 13, 2017

Conversation

axic
Copy link
Member

@axic axic commented Jun 27, 2017

Fixes #1435.

@axic axic force-pushed the functiontype-sig branch from fcfa374 to a226f4a Compare June 27, 2017 11:16
@axic axic requested review from pirapira and chriseth June 27, 2017 11:25
Copy link
Contributor

@chriseth chriseth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strictly, this is about the first four bytes of the hash of the signature, not the signature itself. I know we have msg.sig, but I wonder whether it would make sense to call it identifier or id instead.

On the other hand, this could also be just confusing and sig is an accepted - even if wrong - name for this.

Copy link
Member

@pirapira pirapira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

@pirapira
Copy link
Member

@chriseth identifier does not make sense because overloaded functions share the same identifier but have different hashes of function signatures.

Copy link
Contributor

@chriseth chriseth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update the documentation. Also, there is a test failure:

Invalid error: "Internal compiler error (/home/travis/build/ethereum/solidity/libsolidity/ast/Types.cpp:2513): External signature of function needs declaration

"

scripts/../test/cmdlineTests.sh: line 80: 12148 Aborted                 (core dumped) "$REPO_ROOT"/build/test/solfuzzer --quiet < "$f"

Fuzzer failed on:

		contract C {

			function h() external {

			}

			function f() external returns (uint) {

				function () external g = this.h;

				return g.sig;

			}

		}


@chriseth
Copy link
Contributor

The ABI specification calls this thing "Function Selector". Also msg.sig might sound like a cryptographic signature (especially in the context of a message).

Perhaps we should deprecate msg.sig and use the same word for both contexts.

funSel? functionSelector? selector?

@federicobond
Copy link
Contributor

selector was clear for me, even before reading @chriseth's comment. I'm in favor of deprecating msg.sig and using selector in both contexts.

We can then talk about the function signature as the plain-text representation that is hashed to obtain the function selector.

@axic
Copy link
Member Author

axic commented Jun 28, 2017

It is called as methodIdentifier and externalIdentifier in the compiler interface.

@axic
Copy link
Member Author

axic commented Jun 28, 2017

This works:

                      function h() external {
                      }
                      function f() external returns (uint) {
                              var g = this.h;
                              return g.sig;
                      }

This doesn't:

                      function h() external {
                      }
                      function f() external returns (uint) {
                              function () external g = this.h;
                              return g.sig;
                      }

(Calling g() in both cases works properly and the proper signature is put in the assembly.)

The code fails here:

string FunctionType::externalSignature() const
{
        solAssert(m_declaration != nullptr, "External signature of function needs declaration");

@axic
Copy link
Member Author

axic commented Jun 28, 2017

Probably sig on variables is not a good idea and var should be disabled, so have to check for hasDeclaration().

@axic axic force-pushed the functiontype-sig branch from a226f4a to 1fb0c3d Compare June 28, 2017 17:15
@axic
Copy link
Member Author

axic commented Jul 1, 2017

Something is weird. On Linux it reports:

Running 1373 test cases...
Warning: This is a pre-release compiler version, please do not use it in production.
:5:12: Error: Return argument type uint32 is not implicitly convertible to expected type (type of first return variable) bytes4.
				return this.f.selector;
				       ^-------------^
/home/travis/build/ethereum/solidity/test/../test/libsolidity/SolidityExecutionFramework.h(68): error in "function_types_sig": Compiling contract failed
/home/travis/build/ethereum/solidity/test/libsolidity/../ExecutionFramework.h(72): fatal error in "function_types_sig": critical check !m_output.empty() failed
/home/travis/build/ethereum/solidity/test/libsolidity/SolidityNameAndTypeResolution.cpp(157): fatal error in "function_types_sig": critical check !!sourceAndError.second failed
*** 3 failures detected in test suite "SolidityTests"

But on Windows there is only one failure:

C:/projects/solidity/test/libsolidity/SolidityNameAndTypeResolution.cpp(157): fatal error: in "SolidityNameAndTypeResolution/function_types_sig": critical check !!sourceAndError.second has failed

What Linux reports is correct, but why is it missing on Windows?

@axic
Copy link
Member Author

axic commented Jul 11, 2017

@chriseth any idea why the Windows vs. Linux tests differ?

@chriseth
Copy link
Contributor

No, we have to investigate.

if (m_kind == Kind::External && hasDeclaration())
members.push_back(MemberList::Member(
"selector",
make_shared<IntegerType>(32)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be bytes4 or uint32?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bytes4.

@axic
Copy link
Member Author

axic commented Jul 11, 2017

Difference is: the other compilation failure is part of the end-to-end tests, which is not run on Windows.

@axic axic force-pushed the functiontype-sig branch 5 times, most recently from 5703e70 to 2cd25bd Compare July 11, 2017 16:52
@axic
Copy link
Member Author

axic commented Jul 11, 2017

@chriseth @pirapira @federicobond Added documentation changes so this should be ready.

@axic axic force-pushed the functiontype-sig branch 2 times, most recently from 8ab9ca2 to 38e0b1a Compare July 11, 2017 18:56
}
function f() external returns (bytes4) {
var g = this.h;
return g.selector;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is not detected yet.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chriseth if you know a quick way to solve this, please do

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@axic axic changed the title Add .sig member on function types Add .selector member on function types Jul 27, 2017
@axic
Copy link
Member Author

axic commented Aug 23, 2017

@chriseth the reason we wanted to disable them on variables is most of them don't have a name so the signature cannot be established.

Tha question remains: should we allow it for var when it refers to an actual functions and as such has the name?

@axic axic force-pushed the functiontype-sig branch 3 times, most recently from e45d046 to 2ab217c Compare August 28, 2017 22:09
@axic
Copy link
Member Author

axic commented Aug 28, 2017

@chriseth rebased (man, that was annoying) and I think this is as far as we can go without spending way too much time on it. It just checks if the declaration is available (e.g. has an external signature).

That means var assigning an actual external function works, but assigning anything via a function value type will not since that has no declaration (name).

if (member == "selector")
{
FunctionType const& type = dynamic_cast<FunctionType const&>(*_memberAccess.expression().annotation().type);
utils().popStackElement(type);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not m_context << Instruction::SWAP1 << Instruction::POP;? (and then perhaps a shift left, not sure about that)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the stack should have <address> <signature>.

@axic
Copy link
Member Author

axic commented Aug 29, 2017

Test bound functions. Perhaps for function types the stack also contains the first argument either before or after the function type.

@axic
Copy link
Member Author

axic commented Sep 12, 2017

@chriseth please review (but don't merge yet, will squash some commits)

@@ -2436,6 +2436,11 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const*) con
case Kind::BareDelegateCall:
{
MemberList::MemberMap members;
if (m_kind == Kind::External && hasDeclaration())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't we say that the hasDeclaration() condition is not required?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to give it a try.

@axic axic force-pushed the functiontype-sig branch 3 times, most recently from aeee758 to 0fe2d04 Compare September 13, 2017 08:28
return fun.selector;
}
function h() returns (bytes4) {
function () external returns (bytes4) fun = this.f;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works now, but not sure we are doing the right thing, since the function signature of this function type can be different depending on what function was assigned to it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, but the correct type signature has to be there, since we also have to know it when we want to call the function. What are your worries?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind.

@axic
Copy link
Member Author

axic commented Sep 13, 2017

@chriseth should be ready now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants