-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Tuple ABI support #829
Comments
We can probably special case the tuple case for |
Lets define this as two phases.
|
TIL that tuple components are named in the ABI. Nice |
I'd be interested in tackling this! May need some guidance, but I'll start digging into the contract ABI spec to get some context (not super familiar with ABIs): Let me know if there's any other docs that you think would help give me more context! |
@carver following up on this - was on vacation, going to start looking into this again this week. 👍 |
Any update on this? |
@fabioberger still working on this! Was finishing looking over the contract ABI spec last night to get a better understanding how the tuples / structs work. Was gonna post out any questions I have tonight or tomorrow to clarify what exactly we need / fill in any gaps in my understanding and then get to digging into the implementation tomorrow. 👍 |
@fabioberger just a heads up, I'm getting pulled into some critical stuff at work so most likely not gonna have a chance to dig into this again until the weekend. If you all needed this right now, feel free to pick it up. If not, I'll just keep chugging along with this. 👍🏽 |
@carver / @pipermerriam okay, after messing around with the code in |
@stefanmendoza Encoder classes in |
I was more referring to Jason's suggestion that we update
I know @pipermerriam suggested we just have conditionals for them in the
Yeah, I had ran into a similar issue before... The dependency tree is pretty nasty. If we want to use master (eth-abi 2.x), we'll have to figure out what all needs to be bumped up. For reference: #1056 (comment) |
So the idea would roughly be to create your own registry of eth-abi encoders that have custom implementations, and then call eth-abi's For example, you could subclass The best solution probably modifies |
I'd love to clean this up so that we only use public APIs from cc @kclowes as I think you're working on this. |
@carver / @pipermerriam cool, thanks guys! I'm thinking of splitting up the first chunk of work like this:
Sound like a reasonable approach? We'll probably need to discuss more about what you meant in regards to the formal API in Web3, @pipermerriam. Also @pipermerriam - I looked and @kclowes doesn't seem to have cloned eth_abi or web3.py and pushed them up, so I'm gonna just start digging into these, but @kclowes please let me know if you already have some work done and we can tackle this together if you want! |
👋 Hi Stefan! I have just been poking around with this over the last couple days and trying to get my head wrapped around the problem. I don't have any "work" done to speak of. I'm happy to pick it up though if it looks like you won't have time over the next few days, just let me know! |
Just to clarify, there are two public APIs under discussion here: eth-abi's and web3's. For web3, allowing you override the default eth-abi registry seems pretty reasonable, but this PR won't need to depend on it. For eth-abi, this PR may depend on a new eth-abi API. Maybe a better API than
Seems like a reasonable first pass 👍 |
@carver - So one of the reasons why I was thinking of just making the passive change to the EDIT: On the flip side though, I do think it could get unwieldy to have to pass a registry around to all those methods... 🤔 May need to give it more thought. Potentially have another class that takes a registry and then that has the methods? Maybe an
|
Yeah, it's a reasonable argument, and probably why Ok, to iterate on the class ABICodec:
def __init__(self, registry):
# If you want a different registry, create a new ABICodec instance
# part of me wants to be able to "freeze" the registry at this point, but that's a whole other convo
self._registry = registry
def is_encodable():
def encode_abi():
def encode_single():
def decode_abi():
def decode_single(): The
Someone, somewhere has to keep a reference to the custom registry. So there may be no way around referencing that codec instance a lot. |
@carver Codec was the word I was looking for lol I was thinking of something like a SerDe but couldn't remember the equivalent for an encoder / decoder. 😅 I think this approach makes sense. 👍
Agreed with this, but instead of passing a registry instance to every method call, I think it's a little nicer to instantiate a Codec and pass that around just and call methods on that instead. That's more of what I was thinking. |
Am I correct that basically the main issue here is that there's no way to say you have a custom registry and that everyone should use it? If so, then the codec class makes sense but only really as a wrapper around an updatable reference to the current active registry. As such, I'd expect to see something like this on class ABICodec:
...
def set_registry(self, registry):
self._registry = registry
... Also, were we thinking that this |
Yup, sounds about right.
Yes and no. Because the client has to keep this codec instance around anyway, it's the same to change the registry in these two ways: # the mutable registry way
w3._abi_codec.set_registry(new_registry)
# the immutable registry way
w3._abi_codec = ABICodec(new_registry) I tend to like the immutable approach, but in this particular case I wouldn't cry if we did the mutable one.
I think eth-abi. It seems like something that other eth-abi users could reasonably want. |
Here's a related question that seems important to me: is it |
Right, the consumer would track the codec, and the codec would track the registry.
Yup, that's what I'm suggesting. |
Hey guys, I wanted to let you know that I'm working on a partial solution to this issue. I've got a very specific use case that I need to get working. It's a call to an existing contract method, which both accepts and returns a Thankfully, since my requirements don't demand support for ENS names or any other fancy string handling in the @pipermerriam , FYI, it's looking like I'll be covering all of your "phases" in order to support my use case. I've already got changes working to support |
@feuGeneA cool! So are you essentially just going to house all the logic for tuples here in web3.py? |
@stefanmendoza that's what I'm doing right now. But to be honest I'm not sure whether it belongs in Here's the gist of what I'm doing: The problem is that, while the current code just blindly copies the type names from the ABI and passes them to So my solution is simple: In Again, this logic does seem (to my naive mind) like it could be useful to other users of |
@feuGeneA it'd be good if you could post a pull request with the code you've already got for this as that is often more illustrative than any description can be. It doesn't have to be something that's ready to merge or even something that we plan on merging. |
@pipermerriam Here's the current status of my work in progress: 77d2ed1 I hope you don't cringe too much 😄 I'm definitely just hacking my way through the errors, trying to get my data to flow through. Hopefully the experience will teach us what the solution should look like. |
@feuGeneA Thanks for opening the PR. I'm fine with your approach. Sometimes just throwing code at things till it works and then refining is a totally acceptable way to figure stuff out. |
Note that @stefanmendoza is making progress on the approach for custom ABI registries. I suspect we only need one of those approaches to eventually be merged. Both are exploratory enough that it probably makes sense to continue on both. |
@carver @davesque thanks for the help, guys! Much appreciated. So based on my comment here, do you all agree that the next step would be trying to fix any dependency conflicts with web3.py so we can pull in eth-abi 2.x? Would we want it on master or a separate branch? Or do we want to finish up adding support to eth-abi (dicts, etc.) and have it "feature complete" and then bring 2.x out of beta and uplift web3? I'm leaning more in favor of the latter. |
Okay, my PR #1147 is "done" and ready for review. I've consolidated all the duplicate logic, added quite a few tests, verified that it works for my contract method which accepts and returns a tuple, and generally polished it to my own satisfaction. Please let me know what you think. |
Yeah, that sounds good.
Go ahead and do master, which is already forked from
Hm, that would be great, but... it seems like several people are itching for tuple support now, and since web3 is already on a v5 pre-release I think it's okay to build on the eth-abi pre-release for now. Definitely add issues to eth-abi for things that you think need to happen before v2 goes stable, though! |
@feuGeneA can I ask you and @stefanmendoza to work together on a unified solution? (specifically by commenting on this issue, so that we can all be a part of the conversation) The approach of upgrading to eth-abi v2 with tuple support continues to look promising to me. It would be great if you two could figure out how #1147 might fit into that direction (maybe it's mostly the same, or maybe it is dramatically different, it's not obvious to me yet). |
I must admit that I don't yet fully comprehend how and where the utilization of a custom Despite the
And all of those new helper functions, listed below, are completely independent, so they could be easily transplanted to wherever it is that they should live (
Finally, to help us all reason about these changes, I drew up a crude call graph, just below, to show what uses the functions that have changed. Each bullet is directly used by its direct sub-bullets.
Lots of content here... I hope it's helpful! Please do let me know how you all feel about my assertion that the changes in #1147 aren't significant enough to alter the approach of utilizing a custom Edit: Added some more changes, to support arrays of tuples, and updated links above appropriately, and upped the count of changed/added non-test/non-helper lines to 45. 😄 |
Sweet! I'll check this out tomorrow during the day if I get time; if not, in the evening. Then we can sync up on how we may use the custom registries from |
Looks like the following dependency warnings are showing up on master of web3.py. Saw them in the pip install, so I ran
@carver some PRs to fix this: Will need a release of eth-tester and ethtoken.py. I'm going to work on integrating my eth-abi and |
@stefanmendoza Just FYI, I've also been looking at getting this PR ready to merge. I think that might involve adding a "cloning" feature to the registry in eth-abi. Then, we can just clone the existing registry and swap out a couple of coder classes to get the value-munging behavior we want. Also, I might have some fixes and refactors here and there to add to this PR. |
Any news ? |
Just tried, it's not supported by v5.0.0a4 |
What was wrong?
Tuple types are not supported yet in Web3.py
How can it be fixed?
web3.utils.abi.is_encodable
when elements of the tuple are handled as special cases, like what if the function accepts this tuple as an argument:(address, string, (bytes, bytes32))
and someone passes in('myname.eth', b'already-encoded', ('0x0123', '0x4567'))
One option to consider: write custom encoders for address, bytes*, and string, replacing the default ones. Then
is_encodable
would be replaced entirely witheth_abi.is_encodable
The text was updated successfully, but these errors were encountered: