Upgrade infura (#1341)

* Add infura key argument

* Make some changes and update docs

* Fix config tests

* Set dummy infura_id in test

* Use ci env var

* Set env var in config.yaml

* Remove curly braces

* Create a separate run to initialise env var

* Debug commit

* test ci

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

* Fix setting of env var

Co-authored-by: Bernhard Mueller <b-mueller@users.noreply.github.com>
pull/1345/head
Nikhil Parasaram 5 years ago committed by GitHub
parent df744b863d
commit 27b941791b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .circleci/config.yml
  2. 24
      docs/source/security-analysis.rst
  3. 13
      mythril/ethereum/interface/rpc/client.py
  4. 6
      mythril/interfaces/cli.py
  5. 29
      mythril/mythril/mythril_config.py
  6. 17
      tests/mythril/mythril_config_test.py
  7. 4
      tox.ini

@ -54,9 +54,9 @@ jobs:
working_directory: /home/mythril working_directory: /home/mythril
no_output_timeout: 10m no_output_timeout: 10m
environment: environment:
LC_ALL: en_US.ASCII
LANG: en_US.ASCII LANG: en_US.ASCII
MYTHRIL_DIR: '/home/mythril' MYTHRIL_DIR: '/home/mythril'
INFURA_ID: $INFURA_ID
- store_test_results: - store_test_results:
path: /home/mythril/.tox/output path: /home/mythril/.tox/output

@ -57,15 +57,15 @@ Analyzing On-Chain Contracts
When analyzing contracts on the blockchain, Mythril will by default attempt to query INFURA. You can use the built-in INFURA support or manually configure the RPC settings with the :code:`--rpc` argument. When analyzing contracts on the blockchain, Mythril will by default attempt to query INFURA. You can use the built-in INFURA support or manually configure the RPC settings with the :code:`--rpc` argument.
+--------------------------------+-------------------------------------------------+ +-------------------------------------------------+-------------------------------------------------+
| :code:`--rpc ganache` | Connect to local Ganache | | :code:`--rpc ganache` | Connect to local Ganache |
+--------------------------------+-------------------------------------------------+ +-------------------------------------------------+-------------------------------------------------+
| :code:`--rpc infura-[netname]` | Connect to mainnet, rinkeby, kovan, or ropsten. | | :code:`--rpc infura-[netname] --infura-id <ID>` | Connect to mainnet, rinkeby, kovan, or ropsten. |
+--------------------------------+-------------------------------------------------+ +-------------------------------------------------+-------------------------------------------------+
| :code:`--rpc host:port` | Connect to custom rpc | | :code:`--rpc host:port` | Connect to custom rpc |
+--------------------------------+-------------------------------------------------+ +-------------------------------------------------+-------------------------------------------------+
| :code:`--rpctls <True/False>` | RPC connection over TLS (default: False) | | :code:`--rpctls <True/False>` | RPC connection over TLS (default: False) |
+--------------------------------+-------------------------------------------------+ +-------------------------------------------------+-------------------------------------------------+
To specify a contract address, use :code:`-a <address>` To specify a contract address, use :code:`-a <address>`
@ -73,13 +73,14 @@ Analyze mainnet contract via INFURA:
.. code-block:: bash .. code-block:: bash
myth analyze -a 0x5c436ff914c458983414019195e0f4ecbef9e6dd myth analyze -a 0x5c436ff914c458983414019195e0f4ecbef9e6dd --infura-id <ID>
You can also use the environment variable `INFURA_ID` instead of the cmd line argument or set it in ~/.mythril/config.ini.
Adding the :code:`-l` flag will cause mythril to automatically retrieve dependencies, such as dynamically linked library contracts: Adding the :code:`-l` flag will cause mythril to automatically retrieve dependencies, such as dynamically linked library contracts:
.. code-block:: bash .. code-block:: bash
myth -v4 analyze -l -a 0xEbFD99838cb0c132016B9E117563CB41f2B02264 myth -v4 analyze -l -a 0xEbFD99838cb0c132016B9E117563CB41f2B02264 --infura-id <ID>
****************** ******************
Speed vs. Coverage Speed vs. Coverage
@ -88,3 +89,4 @@ Speed vs. Coverage
The execution timeout can be specified with the :code:`--execution-timeout <seconds>` argument. When the timeout is reached, mythril will stop analysis and print out all currently found issues. The execution timeout can be specified with the :code:`--execution-timeout <seconds>` argument. When the timeout is reached, mythril will stop analysis and print out all currently found issues.
The maximum recursion depth for the symbolic execution engine can be controlled with the :code:`--max-depth` argument. The default value is 22. Lowering this value will decrease the number of explored states and analysis time, while increasing this number will increase the number of explored states and increase analysis time. For some contracts, it helps to fine tune this number to get the best analysis results. The maximum recursion depth for the symbolic execution engine can be controlled with the :code:`--max-depth` argument. The default value is 22. Lowering this value will decrease the number of explored states and analysis time, while increasing this number will increase the number of explored states and increase analysis time. For some contracts, it helps to fine tune this number to get the best analysis results.
-

@ -52,11 +52,20 @@ class EthJsonRpc(BaseClient):
:return: :return:
""" """
params = params or [] params = params or []
data = {"jsonrpc": "2.0", "method": method, "params": params, "id": _id} data = {
"jsonrpc": "2.0",
"method": method,
"params": params,
"id": _id,
}
scheme = "http" scheme = "http"
if self.tls: if self.tls:
scheme += "s" scheme += "s"
url = "{}://{}:{}".format(scheme, self.host, self.port) if self.host:
url = "{}://{}:{}".format(scheme, self.host, self.port)
else:
url = "{}".format(scheme)
headers = {"Content-Type": JSON_MEDIA_TYPE} headers = {"Content-Type": JSON_MEDIA_TYPE}
log.debug("rpc send: %s" % json.dumps(data)) log.debug("rpc send: %s" % json.dumps(data))
try: try:

@ -374,6 +374,10 @@ def create_analyzer_parser(analyzer_parser: ArgumentParser):
action="store_true", action="store_true",
help="analyze a truffle project (run from project dir)", help="analyze a truffle project (run from project dir)",
) )
commands.add_argument(
"--infura-id", help="set infura id for onchain analysis",
)
options = analyzer_parser.add_argument_group("options") options = analyzer_parser.add_argument_group("options")
options.add_argument( options.add_argument(
"-m", "-m",
@ -529,6 +533,8 @@ def set_config(args: Namespace):
:return: modified config :return: modified config
""" """
config = MythrilConfig() config = MythrilConfig()
if args.__dict__.get("infura_id", None):
config.set_api_infura_id(args.infura_id)
if ( if (
args.command in ANALYZE_LIST args.command in ANALYZE_LIST
and (args.dynld or not args.no_onchain_storage_access) and (args.dynld or not args.no_onchain_storage_access)

@ -23,6 +23,7 @@ class MythrilConfig:
""" """
def __init__(self): def __init__(self):
self.infura_id = os.getenv("INFURA_ID") # type: str
self.mythril_dir = self._init_mythril_dir() self.mythril_dir = self._init_mythril_dir()
self.config_path = os.path.join(self.mythril_dir, "config.ini") self.config_path = os.path.join(self.mythril_dir, "config.ini")
self.leveldb_dir = None self.leveldb_dir = None
@ -30,6 +31,9 @@ class MythrilConfig:
self.eth = None # type: Optional[EthJsonRpc] self.eth = None # type: Optional[EthJsonRpc]
self.eth_db = None # type: Optional[EthLevelDB] self.eth_db = None # type: Optional[EthLevelDB]
def set_api_infura_id(self, id):
self.infura_id = id
@staticmethod @staticmethod
def _init_mythril_dir() -> str: def _init_mythril_dir() -> str:
""" """
@ -83,12 +87,17 @@ class MythrilConfig:
if not config.has_option("defaults", "dynamic_loading"): if not config.has_option("defaults", "dynamic_loading"):
self._add_dynamic_loading_option(config) self._add_dynamic_loading_option(config)
if not config.has_option("defaults", "infura_id"):
config.set("defaults", "infura_id", "")
with codecs.open(self.config_path, "w", "utf-8") as fp: with codecs.open(self.config_path, "w", "utf-8") as fp:
config.write(fp) config.write(fp)
leveldb_dir = config.get( leveldb_dir = config.get(
"defaults", "leveldb_dir", fallback=leveldb_default_path "defaults", "leveldb_dir", fallback=leveldb_default_path
) )
if not self.infura_id:
self.infura_id = config.get("defaults", "infura_id", fallback="")
self.leveldb_dir = os.path.expanduser(leveldb_dir) self.leveldb_dir = os.path.expanduser(leveldb_dir)
@staticmethod @staticmethod
@ -167,7 +176,9 @@ class MythrilConfig:
def set_api_rpc_infura(self) -> None: def set_api_rpc_infura(self) -> None:
"""Set the RPC mode to INFURA on Mainnet.""" """Set the RPC mode to INFURA on Mainnet."""
log.info("Using INFURA Main Net for RPC queries") log.info("Using INFURA Main Net for RPC queries")
self.eth = EthJsonRpc("mainnet.infura.io", 443, True) self.eth = EthJsonRpc(
"mainnet.infura.io/v3/{}".format(self.infura_id), None, True
)
def set_api_rpc(self, rpc: str = None, rpctls: bool = False) -> None: def set_api_rpc(self, rpc: str = None, rpctls: bool = False) -> None:
""" """
@ -178,8 +189,20 @@ class MythrilConfig:
rpcconfig = ("localhost", 7545, False) rpcconfig = ("localhost", 7545, False)
else: else:
m = re.match(r"infura-(.*)", rpc) m = re.match(r"infura-(.*)", rpc)
if m and m.group(1) in ["mainnet", "rinkeby", "kovan", "ropsten"]: if m and m.group(1) in ["mainnet", "rinkeby", "kovan", "ropsten"]:
rpcconfig = (m.group(1) + ".infura.io", 443, True) if self.infura_id in (None, ""):
raise CriticalError(
"Infura key not provided. Use --infura-id <INFURA_ID> "
"or set it in the environment variable INFURA_ID "
"or in the ~/.mythril/config.ini file'"
)
rpcconfig = (
"{}.infura.io/v3/{}".format(m.group(1), self.infura_id),
None,
True,
)
else: else:
try: try:
host, port = rpc.split(":") host, port = rpc.split(":")
@ -191,7 +214,7 @@ class MythrilConfig:
if rpcconfig: if rpcconfig:
log.info("Using RPC settings: %s" % str(rpcconfig)) log.info("Using RPC settings: %s" % str(rpcconfig))
self.eth = EthJsonRpc(rpcconfig[0], int(rpcconfig[1]), rpcconfig[2]) self.eth = EthJsonRpc(rpcconfig[0], rpcconfig[1], rpcconfig[2])
else: else:
raise CriticalError("Invalid RPC settings, check help for details.") raise CriticalError("Invalid RPC settings, check help for details.")

@ -1,4 +1,5 @@
import pytest import pytest
import os
from configparser import ConfigParser from configparser import ConfigParser
from pathlib import Path from pathlib import Path
@ -13,16 +14,15 @@ def test_config_path_dynloading():
Path(__file__).parent.parent / "testdata/mythril_config_inputs/config.ini" Path(__file__).parent.parent / "testdata/mythril_config_inputs/config.ini"
) )
config.set_api_from_config_path() config.set_api_from_config_path()
assert config.eth.host == "mainnet.infura.io" assert "mainnet.infura.io/v3/" in config.eth.host
assert config.eth.port == 443
rpc_types_tests = [ rpc_types_tests = [
("infura", "mainnet.infura.io", 443, True), ("infura", "mainnet.infura.io/v3/", None, True),
("ganache", "localhost", 7545, True), ("ganache", "localhost", None, True),
("infura-rinkeby", "rinkeby.infura.io", 443, True), ("infura-rinkeby", "rinkeby.infura.io/v3/", None, True),
("infura-ropsten", "ropsten.infura.io", 443, True), ("infura-ropsten", "ropsten.infura.io/v3/", None, True),
("infura-kovan", "kovan.infura.io", 443, True), ("infura-kovan", "kovan.infura.io/v3/", None, True),
("localhost", "localhost", 8545, True), ("localhost", "localhost", 8545, True),
("localhost:9022", "localhost", 9022, True), ("localhost:9022", "localhost", 9022, True),
("pinfura", None, None, False), ("pinfura", None, None, False),
@ -35,8 +35,7 @@ def test_set_rpc(rpc_type, host, port, success):
config = MythrilConfig() config = MythrilConfig()
if success: if success:
config._set_rpc(rpc_type) config._set_rpc(rpc_type)
assert config.eth.host == host assert host in config.eth.host
assert config.eth.port == port
else: else:
with pytest.raises(CriticalError): with pytest.raises(CriticalError):
config._set_rpc(rpc_type) config._set_rpc(rpc_type)

@ -5,7 +5,7 @@ envlist = py36
deps = deps =
pytest pytest
pytest-mock pytest-mock
passenv = MYTHRIL_DIR = {homedir} passenv = MYTHRIL_DIR INFURA_ID
whitelist_externals = mkdir whitelist_externals = mkdir
commands = commands =
mkdir -p {toxinidir}/tests/testdata/outputs_current/ mkdir -p {toxinidir}/tests/testdata/outputs_current/
@ -24,7 +24,7 @@ deps =
pytest pytest
pytest-mock pytest-mock
pytest-cov pytest-cov
passenv = MYTHRIL_DIR = {homedir} passenv = MYTHRIL_DIR INFURA_ID
whitelist_externals = mkdir whitelist_externals = mkdir
commands = commands =
mypy --follow-imports=silent --warn-unused-ignores --ignore-missing-imports --no-strict-optional mythril mypy --follow-imports=silent --warn-unused-ignores --ignore-missing-imports --no-strict-optional mythril

Loading…
Cancel
Save