Description
Overview
This is a proposal to add comprehensive type encoding and decoding tests to go-ethereum, including all of the Pack*
and Unpack*
functions in accounts/abi
and accounts/abi/bind
. The tests would also test how the values are sent to/from smart contracts and therefore also check the full consensus mechanism as it relates to go-ethereum.
Background
Several recent bugs have exposed inconsistencies with how data types are encoded/decoded from the ABI (bugs fixed in Solidity 0.5.10 release, bugs fixed in Solidity 0.5.11 release, #20269), as well as how geth produces valid blocks (regressions fixed in go-ethereum 1.9.5 release). Comprehensive testing would help catch these during the development cycle.
Approach
Part 1: unify, fix and DRY
- Refactor the disparate encoding/decoding packing/unpacking tests in
pack_test.go
,unpack_test.go
andtopics_test.go
to use a unified set of test cases. It is highly likely this will expose additional issues that should be addressed. - Unify the encoding/decoding code across the
Pack*
andUnpack*
functions inaccounts/abi
andaccounts/abi/bind
. The most complete and DRY of these looks to be inaccounts/abi
. Some of the changes will probably have to be percolated up from the private functions to, for example, rely on a unified primary key acrossabi.Type.Type
,abi.Type.T
andabi.Type.Kind
. Some of the helper functions (toGoType()
, etc.) may need to be further pulled apart or adjusted to handle the difference between decoding "standard" ABI-encoded bytes and how indexed events (i.e., transaction logs) are encoded.
Part 2: comprehensive end-to-end tests
- Add dockerized
solc
to the Travis CI configuration so that we can compile contracts as part of Go tests. - Build on the extensive tests in
bind_test.go
and dynamically generate getter/setter smart contracts for all base types and select dynamic (composite) types, including both indexed and non-indexed events (where appropriate).- If we want to be efficient, it would be a single smart contract compiled by the test and deployed to an in-memory SimulatedBackend with sufficiently high gas limit (100 million?) to handle it in one gulp.
- Better, though, would be to have the smart contract divided into pieces (automatically) and run through full geth PoA to test block composition.
- After deploying the smart contract to an in-memory blockchain, it would then proceed to call each setter and getter, and subscribe to the events, comparing what was sent to the blockchain to what was received.
Implementation notes
Resolving this issue in the way described above is a fairly large amount of work, even for someone with detailed knowledge of Go, go-ethereum and Solidity. It could be ~2 months of full time engineering effort.