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

Only try to resolve ENS names on mainnet #1037

Merged
merged 1 commit into from
Sep 5, 2018

Conversation

ankitchiplunkar
Copy link
Contributor

What was wrong?

Related to Issue # #887

How was it fixed?

  1. Added a check in abi_name_resolver to check if the chain is mainnet.
  2. Added another check in the same resolver to check if the ens instance is StaticENS to enable passing of old tests.
  3. Added tests which verify the change
  4. Updated the docs

Cute Animal Picture

Put a link to a cute animal picture inside the parenthesis-->

@ankitchiplunkar ankitchiplunkar changed the title https://github.com/ethereum/web3.py/issues/887 Only try to resolve ENS names on mainnet Aug 31, 2018
@ankitchiplunkar
Copy link
Contributor Author

@carver @pipermerriam would love any inputs on this PR.

Copy link
Collaborator

@carver carver left a comment

Choose a reason for hiding this comment

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

Cool, looks like it's nearly there! Most important is the change so that the tests run offline (and so that we don't inadvertently DoS Infura if we run a lot of tests simultaneously).

@@ -137,6 +138,8 @@ def abi_ens_resolver(w3, abi_type, val):
raise InvalidAddress("Could not look up name, because no web3 connection available")
elif w3.ens is None:
raise InvalidAddress("Could not look up name, because ENS is set to None")
elif int(w3.net.version) is not 1 and not isinstance(w3.ens, StaticENS):
raise InvalidAddress("Could not look up name, because web3 is not connected to mainnet")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would you add the name val to this message and the ones above it? Something like:

"Could not look up name %r, because web3 is not connected to mainnet" % val

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

def test_pass_name_resolver_mainnet():
url = "https://mainnet.infura.io/"
w3 = w3_name_resolver(url)
w3.eth.getBalance("ethereum.eth")
Copy link
Collaborator

Choose a reason for hiding this comment

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

This looks like it's actually hitting Infura for the test, right? Tests should be able to run while disconnected from the Internet.

One option is to use construct_fixture_middleware to return the network id (probably injected at layer 0).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Pushed the test offline but the BaseProvider was missing several methods which had to be implemented eg eth_getBlockByNumber, eth_call and eth_getBalance.
Tried to enable these methods using construct_fixture_middleware at layer 0 but the command w3.eth.getBalance(name) would call eth_getBalance --> eth_call --> eth_getBlockByNumber (which would again throw method not implemented error).

Maybe after 2-3 recusrive calls the method construct_fixture_middleware fails.

Have bypassed this issue by letting pytest catch the NotImplementedError do tell me if this is not an acceptable solution.

Copy link
Member

Choose a reason for hiding this comment

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

@carver drive-by-idea.

  • fixture_recorder_middleware

Lets you connect whatever provider you like, make some calls, and then export the request/response data in a format that could then be passed into construct_fixture_middleware to emulate the request/responses.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ooh, neat idea.

url = "https://kovan.infura.io/"
w3 = w3_name_resolver(url)
with pytest.raises(InvalidAddress):
w3.eth.getBalance("ethereum.eth")
Copy link
Collaborator

Choose a reason for hiding this comment

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

same here

})
w3.middleware_stack.inject(return_chain_on_mainnet, layer=0)
with pytest.raises(NotImplementedError):
w3.eth.getBalance('ethereum.eth')
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this could end up as a passing test even if the implementation is broken, too easily. It's expected to struggle with the right solution here. Part of the reason this change wasn't made yet is that testing it well is tricky. :)

StaticENS seems like an obvious choice, but decide whether to look up the name with an isinstance on that class, it's problematic to use in the test. Maybe reimplement a new special StaticENS in the test module and use that instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Have created a new ENS class in the test for resolving this middleware

because ENS is set to None" % val)
elif int(w3.net.version) is not 1 and not isinstance(w3.ens, StaticENS):
raise InvalidAddress("Could not look up name %r, \
because web3 is not connected to mainnet" % val)
Copy link
Collaborator

Choose a reason for hiding this comment

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

nitpick

We've been avoiding line continuations like that in these projects. Our style guide is here: https://github.com/pipermerriam/ethereum-dev-tactical-manual/blob/master/style-guide.md#multi-line-statements

The preferred style is something like:

raise InvalidAddress(
  "Could not look up name %r, "
  "because web3 is not connected to mainnet" % (
    val,
  )
)

(I broke up the lines a lot more than you probably need to, I was just demonstrating the preferred newline locations on a really long line)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Accepted the changes

'net_version': '2',
})
w3.middleware_stack.inject(return_chain_on_mainnet, layer=0)
with pytest.raises(InvalidAddress):
Copy link
Collaborator

Choose a reason for hiding this comment

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

This test can now confirm that the name shows up in the exception with something like:

with pytest.raises(InvalidAddress, match='.*ethereum\.eth.*'):

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@carver carver force-pushed the ankit/ens_mainnet_middleware branch from 11798b5 to 606ee3a Compare September 5, 2018 16:38
Copy link
Collaborator

@carver carver left a comment

Choose a reason for hiding this comment

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

LGTM! I just rebased so that the doctest would pass. Will merge after it turns green.

@carver carver merged commit e76911f into ethereum:master Sep 5, 2018
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.

3 participants