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

accounts/abi: handle named ouputs prefixed with underscores #15766

Merged
merged 3 commits into from
Dec 29, 2017

Conversation

karalabe
Copy link
Member

I've found this issue while trying to wrap the smart contracts from Akasha.

If a smart contract has named outputs (i.e. all of the outputs have names), abigen will group them into an on-the-fly generated struct, instead of simply returning a gazillion return value:

// Solidity: function resolve(_node bytes32) constant returns(akashaId bytes32, addr address, donationsEnabled bool, fn uint8, digestSize uint8, hash bytes32)
func (_ProfileResolver *ProfileResolverSession) Resolve(_node [32]byte) (struct {
	AkashaId         [32]byte
	Addr             common.Address
	DonationsEnabled bool
	Fn               uint8
	DigestSize       uint8
	Hash             [32]byte
}, error) {
	return _ProfileResolver.Contract.Resolve(&_ProfileResolver.CallOpts, _node)
}

For the above example, abigen can convert the return names (e.g. akashaId) into output struct field names (e.g. AkashaId) by capitalizing the first letter. Similarly, the abi package can also unpack the fields using the same logic.

Unfortunately, Akasha doesn't name its return values like that, rather it prepends an underscore in front of all the names, resulting in the following binding:

// Solidity: function resolve(_node bytes32) constant returns(_akashaId bytes32, _addr address, _donationsEnabled bool, _fn uint8, _digestSize uint8, _hash bytes32)
func (_ProfileResolver *ProfileResolverSession) Resolve(_node [32]byte) (struct {
	_akashaId         [32]byte
	_addr             common.Address
	_donationsEnabled bool
	_fn               uint8
	_digestSize       uint8
	_hash             [32]byte
}, error) {
	return _ProfileResolver.Contract.Resolve(&_ProfileResolver.CallOpts, _node)
}

Of course trying to run the above generated code will fail at two locations:

  • We can't unmarshal the returned data fields into _fieldname fields, since they are private.
  • The abi package cannot match the fields with the returns, since it only capitalizes.

This PR solves the underlying issue by having a pre-processing step in both abigen and also in abi, where we discard all prefixing underscores from variable names before trying to generate output structs, as well as before trying to match the deserialized outputs into said struct.

The PR also adds a live test case (backed by a simulated backend) to verify that both binding underscores work (i.e. they compile and generate the correct code), as well as unmarshalling works (i.e. the test creates a live contract and retrieves data from it).

Copy link
Contributor

@holiman holiman left a comment

Choose a reason for hiding this comment

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

LGTM

@karalabe karalabe merged commit b973176 into ethereum:master Dec 29, 2017
mariameda pushed a commit to NiluPlatform/go-nilu that referenced this pull request Aug 23, 2018
…#15766)

* accounts/abi: handle named ouputs prefixed with underscores

* accounts/abi: handle collinding outputs for struct unpacks

* accounts: handle purely underscore output names
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.

None yet

2 participants