Refactor and add setup.py

pull/2/head
Bernhard Mueller 7 years ago
parent 2e0746eb5f
commit d76d5ec528
  1. 0
      LICENSE
  2. 4
      README.md
  3. 12
      ether/jsonrpc.py
  4. 4
      ether/util.py
  5. 3
      mythril
  6. 1
      requirements.txt
  7. 8
      rpc/__init__.py
  8. 726
      rpc/client.py
  9. 8
      rpc/constants.py
  10. 18
      rpc/exceptions.py
  11. 38
      rpc/utils.py
  12. 57
      setup.py

@ -83,3 +83,7 @@ $ ./mythril.py -d --txid 0x23112645da9ae684270de843faaeb44918c79a09e019d3a6cf8b8
```
Note: If you want to get code from the Ethereum mainnet, it is easier to download it from [Etherscan](https://etherscan.io).
## Credit
JSON RPC library is adapted from [ethjsonrpc](https://github.com/ConsenSys/ethjsonrpc) (it doesn't seem to be maintained anymore, and I needed to make some changes to it).

@ -1,12 +0,0 @@
from ethjsonrpc import EthJsonRpc
class EthJsonRpcWithDebug(EthJsonRpc):
def getBlockRlp(self, number=0):
return self._call('debug_getBlockRlp', [number])
def traceTransaction(self, txHash):
return self._call('debug_traceTransaction', [txHash])

@ -1,4 +1,4 @@
from ether.jsonrpc import EthJsonRpcWithDebug
from rpc.client import EthJsonRpc
import codecs
@ -14,7 +14,7 @@ def bytecode_from_blockchain(creation_tx_hash, rpc_host='127.0.0.1', rpc_port=85
creation_tx_hash = ID of transaction that created the contract.
"""
eth = EthJsonRpcWithDebug(rpc_host, rpc_port)
eth = EthJsonRpc(rpc_host, rpc_port)
trace = eth.traceTransaction(creation_tx_hash)

@ -4,11 +4,10 @@
http://www.github.com/b-mueller/mythril
"""
from ether import asm,evm
from ether import asm,evm,util
import sys
import codecs
import argparse
import util
def exitWithError(message):

@ -1,2 +1 @@
ethereum==2.0.4
ethjsonrpc==0.3.0

@ -0,0 +1,8 @@
from ethjsonrpc.client import (EthJsonRpc, ParityEthJsonRpc,
ETH_DEFAULT_RPC_PORT, GETH_DEFAULT_RPC_PORT,
PYETHAPP_DEFAULT_RPC_PORT)
from ethjsonrpc.exceptions import (ConnectionError, BadStatusCodeError,
BadJsonError, BadResponseError)
from ethjsonrpc.utils import wei_to_ether, ether_to_wei

@ -0,0 +1,726 @@
import json
import warnings
import requests
from requests.adapters import HTTPAdapter
from requests.exceptions import ConnectionError as RequestsConnectionError
from ethereum import utils
from ethereum.abi import encode_abi, decode_abi
from ethjsonrpc.constants import BLOCK_TAGS, BLOCK_TAG_LATEST
from ethjsonrpc.utils import hex_to_dec, clean_hex, validate_block
from ethjsonrpc.exceptions import (ConnectionError, BadStatusCodeError,
BadJsonError, BadResponseError)
GETH_DEFAULT_RPC_PORT = 8545
ETH_DEFAULT_RPC_PORT = 8545
PARITY_DEFAULT_RPC_PORT = 8545
PYETHAPP_DEFAULT_RPC_PORT = 4000
MAX_RETRIES = 3
JSON_MEDIA_TYPE = 'application/json'
'''
This code is adapted from: https://github.com/ConsenSys/ethjsonrpc
'''
class EthJsonRpc(object):
'''
Ethereum JSON-RPC client class
'''
DEFAULT_GAS_PER_TX = 90000
DEFAULT_GAS_PRICE = 50 * 10**9 # 50 gwei
def __init__(self, host='localhost', port=GETH_DEFAULT_RPC_PORT, tls=False):
self.host = host
self.port = port
self.tls = tls
self.session = requests.Session()
self.session.mount(self.host, HTTPAdapter(max_retries=MAX_RETRIES))
def _call(self, method, params=None, _id=1):
params = params or []
data = {
'jsonrpc': '2.0',
'method': method,
'params': params,
'id': _id,
}
scheme = 'http'
if self.tls:
scheme += 's'
url = '{}://{}:{}'.format(scheme, self.host, self.port)
headers = {'Content-Type': JSON_MEDIA_TYPE}
try:
r = self.session.post(url, headers=headers, data=json.dumps(data))
except RequestsConnectionError:
raise ConnectionError
if r.status_code / 100 != 2:
raise BadStatusCodeError(r.status_code)
try:
response = r.json()
except ValueError:
raise BadJsonError(r.text)
try:
return response['result']
except KeyError:
raise BadResponseError(response)
def _encode_function(self, signature, param_values):
prefix = utils.big_endian_to_int(utils.sha3(signature)[:4])
if signature.find('(') == -1:
raise RuntimeError('Invalid function signature. Missing "(" and/or ")"...')
if signature.find(')') - signature.find('(') == 1:
return utils.encode_int(prefix)
types = signature[signature.find('(') + 1: signature.find(')')].split(',')
encoded_params = encode_abi(types, param_values)
return utils.zpad(utils.encode_int(prefix), 4) + encoded_params
################################################################################
# high-level methods
################################################################################
def transfer(self, from_, to, amount):
'''
Send wei from one address to another
'''
return self.eth_sendTransaction(from_address=from_, to_address=to, value=amount)
def create_contract(self, from_, code, gas, sig=None, args=None):
'''
Create a contract on the blockchain from compiled EVM code. Returns the
transaction hash.
'''
from_ = from_ or self.eth_coinbase()
if sig is not None and args is not None:
types = sig[sig.find('(') + 1: sig.find(')')].split(',')
encoded_params = encode_abi(types, args)
code += encoded_params.encode('hex')
return self.eth_sendTransaction(from_address=from_, gas=gas, data=code)
def get_contract_address(self, tx):
'''
Get the address for a contract from the transaction that created it
'''
receipt = self.eth_getTransactionReceipt(tx)
return receipt['contractAddress']
def call(self, address, sig, args, result_types):
'''
Call a contract function on the RPC server, without sending a
transaction (useful for reading data)
'''
data = self._encode_function(sig, args)
data_hex = data.encode('hex')
response = self.eth_call(to_address=address, data=data_hex)
return decode_abi(result_types, response[2:].decode('hex'))
def call_with_transaction(self, from_, address, sig, args, gas=None, gas_price=None, value=None):
'''
Call a contract function by sending a transaction (useful for storing
data)
'''
gas = gas or self.DEFAULT_GAS_PER_TX
gas_price = gas_price or self.DEFAULT_GAS_PRICE
data = self._encode_function(sig, args)
data_hex = data.encode('hex')
return self.eth_sendTransaction(from_address=from_, to_address=address, data=data_hex, gas=gas,
gas_price=gas_price, value=value)
################################################################################
# JSON-RPC methods
################################################################################
def web3_clientVersion(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#web3_clientversion
TESTED
'''
return self._call('web3_clientVersion')
def web3_sha3(self, data):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#web3_sha3
TESTED
'''
data = str(data).encode('hex')
return self._call('web3_sha3', [data])
def net_version(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#net_version
TESTED
'''
return self._call('net_version')
def net_listening(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#net_listening
TESTED
'''
return self._call('net_listening')
def net_peerCount(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#net_peercount
TESTED
'''
return hex_to_dec(self._call('net_peerCount'))
def eth_protocolVersion(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_protocolversion
TESTED
'''
return self._call('eth_protocolVersion')
def eth_syncing(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_syncing
TESTED
'''
return self._call('eth_syncing')
def eth_coinbase(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_coinbase
TESTED
'''
return self._call('eth_coinbase')
def eth_mining(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_mining
TESTED
'''
return self._call('eth_mining')
def eth_hashrate(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_hashrate
TESTED
'''
return hex_to_dec(self._call('eth_hashrate'))
def eth_gasPrice(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gasprice
TESTED
'''
return hex_to_dec(self._call('eth_gasPrice'))
def eth_accounts(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_accounts
TESTED
'''
return self._call('eth_accounts')
def eth_blockNumber(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_blocknumber
TESTED
'''
return hex_to_dec(self._call('eth_blockNumber'))
def eth_getBalance(self, address=None, block=BLOCK_TAG_LATEST):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getbalance
TESTED
'''
address = address or self.eth_coinbase()
block = validate_block(block)
return hex_to_dec(self._call('eth_getBalance', [address, block]))
def eth_getStorageAt(self, address=None, position=0, block=BLOCK_TAG_LATEST):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getstorageat
TESTED
'''
block = validate_block(block)
return self._call('eth_getStorageAt', [address, hex(position), block])
def eth_getTransactionCount(self, address, block=BLOCK_TAG_LATEST):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactioncount
TESTED
'''
block = validate_block(block)
return hex_to_dec(self._call('eth_getTransactionCount', [address, block]))
def eth_getBlockTransactionCountByHash(self, block_hash):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblocktransactioncountbyhash
TESTED
'''
return hex_to_dec(self._call('eth_getBlockTransactionCountByHash', [block_hash]))
def eth_getBlockTransactionCountByNumber(self, block=BLOCK_TAG_LATEST):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblocktransactioncountbynumber
TESTED
'''
block = validate_block(block)
return hex_to_dec(self._call('eth_getBlockTransactionCountByNumber', [block]))
def eth_getUncleCountByBlockHash(self, block_hash):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclecountbyblockhash
TESTED
'''
return hex_to_dec(self._call('eth_getUncleCountByBlockHash', [block_hash]))
def eth_getUncleCountByBlockNumber(self, block=BLOCK_TAG_LATEST):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclecountbyblocknumber
TESTED
'''
block = validate_block(block)
return hex_to_dec(self._call('eth_getUncleCountByBlockNumber', [block]))
def eth_getCode(self, address, default_block=BLOCK_TAG_LATEST):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getcode
NEEDS TESTING
'''
if isinstance(default_block, basestring):
if default_block not in BLOCK_TAGS:
raise ValueError
return self._call('eth_getCode', [address, default_block])
def eth_sign(self, address, data):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
NEEDS TESTING
'''
return self._call('eth_sign', [address, data])
def eth_sendTransaction(self, to_address=None, from_address=None, gas=None, gas_price=None, value=None, data=None,
nonce=None):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendtransaction
NEEDS TESTING
'''
params = {}
params['from'] = from_address or self.eth_coinbase()
if to_address is not None:
params['to'] = to_address
if gas is not None:
params['gas'] = hex(gas)
if gas_price is not None:
params['gasPrice'] = clean_hex(gas_price)
if value is not None:
params['value'] = clean_hex(value)
if data is not None:
params['data'] = data
if nonce is not None:
params['nonce'] = hex(nonce)
return self._call('eth_sendTransaction', [params])
def eth_sendRawTransaction(self, data):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendrawtransaction
NEEDS TESTING
'''
return self._call('eth_sendRawTransaction', [data])
def eth_call(self, to_address, from_address=None, gas=None, gas_price=None, value=None, data=None,
default_block=BLOCK_TAG_LATEST):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_call
NEEDS TESTING
'''
if isinstance(default_block, basestring):
if default_block not in BLOCK_TAGS:
raise ValueError
obj = {}
obj['to'] = to_address
if from_address is not None:
obj['from'] = from_address
if gas is not None:
obj['gas'] = hex(gas)
if gas_price is not None:
obj['gasPrice'] = clean_hex(gas_price)
if value is not None:
obj['value'] = value
if data is not None:
obj['data'] = data
return self._call('eth_call', [obj, default_block])
def eth_estimateGas(self, to_address=None, from_address=None, gas=None, gas_price=None, value=None, data=None,
default_block=BLOCK_TAG_LATEST):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_estimategas
NEEDS TESTING
'''
if isinstance(default_block, basestring):
if default_block not in BLOCK_TAGS:
raise ValueError
obj = {}
if to_address is not None:
obj['to'] = to_address
if from_address is not None:
obj['from'] = from_address
if gas is not None:
obj['gas'] = hex(gas)
if gas_price is not None:
obj['gasPrice'] = clean_hex(gas_price)
if value is not None:
obj['value'] = value
if data is not None:
obj['data'] = data
return hex_to_dec(self._call('eth_estimateGas', [obj, default_block]))
def eth_getBlockByHash(self, block_hash, tx_objects=True):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbyhash
TESTED
'''
return self._call('eth_getBlockByHash', [block_hash, tx_objects])
def eth_getBlockByNumber(self, block=BLOCK_TAG_LATEST, tx_objects=True):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbynumber
TESTED
'''
block = validate_block(block)
return self._call('eth_getBlockByNumber', [block, tx_objects])
def eth_getTransactionByHash(self, tx_hash):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyhash
TESTED
'''
return self._call('eth_getTransactionByHash', [tx_hash])
def eth_getTransactionByBlockHashAndIndex(self, block_hash, index=0):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyblockhashandindex
TESTED
'''
return self._call('eth_getTransactionByBlockHashAndIndex', [block_hash, hex(index)])
def eth_getTransactionByBlockNumberAndIndex(self, block=BLOCK_TAG_LATEST, index=0):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyblocknumberandindex
TESTED
'''
block = validate_block(block)
return self._call('eth_getTransactionByBlockNumberAndIndex', [block, hex(index)])
def eth_getTransactionReceipt(self, tx_hash):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionreceipt
TESTED
'''
return self._call('eth_getTransactionReceipt', [tx_hash])
def eth_getUncleByBlockHashAndIndex(self, block_hash, index=0):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclebyblockhashandindex
TESTED
'''
return self._call('eth_getUncleByBlockHashAndIndex', [block_hash, hex(index)])
def eth_getUncleByBlockNumberAndIndex(self, block=BLOCK_TAG_LATEST, index=0):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclebyblocknumberandindex
TESTED
'''
block = validate_block(block)
return self._call('eth_getUncleByBlockNumberAndIndex', [block, hex(index)])
def eth_getCompilers(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getcompilers
TESTED
'''
return self._call('eth_getCompilers')
def eth_compileSolidity(self, code):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compilesolidity
TESTED
'''
return self._call('eth_compileSolidity', [code])
def eth_compileLLL(self, code):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compilelll
N/A
'''
return self._call('eth_compileLLL', [code])
def eth_compileSerpent(self, code):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compileserpent
N/A
'''
return self._call('eth_compileSerpent', [code])
def eth_newFilter(self, from_block=BLOCK_TAG_LATEST, to_block=BLOCK_TAG_LATEST, address=None, topics=None):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newfilter
NEEDS TESTING
'''
_filter = {
'fromBlock': from_block,
'toBlock': to_block,
'address': address,
'topics': topics,
}
return self._call('eth_newFilter', [_filter])
def eth_newBlockFilter(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newblockfilter
TESTED
'''
return self._call('eth_newBlockFilter')
def eth_newPendingTransactionFilter(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newpendingtransactionfilter
TESTED
'''
return hex_to_dec(self._call('eth_newPendingTransactionFilter'))
def eth_uninstallFilter(self, filter_id):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_uninstallfilter
NEEDS TESTING
'''
return self._call('eth_uninstallFilter', [filter_id])
def eth_getFilterChanges(self, filter_id):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterchanges
NEEDS TESTING
'''
return self._call('eth_getFilterChanges', [filter_id])
def eth_getFilterLogs(self, filter_id):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterlogs
NEEDS TESTING
'''
return self._call('eth_getFilterLogs', [filter_id])
def eth_getLogs(self, filter_object):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs
NEEDS TESTING
'''
return self._call('eth_getLogs', [filter_object])
def eth_getWork(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getwork
TESTED
'''
return self._call('eth_getWork')
def eth_submitWork(self, nonce, header, mix_digest):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_submitwork
NEEDS TESTING
'''
return self._call('eth_submitWork', [nonce, header, mix_digest])
def eth_submitHashrate(self, hash_rate, client_id):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_submithashrate
TESTED
'''
return self._call('eth_submitHashrate', [hex(hash_rate), client_id])
def db_putString(self, db_name, key, value):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#db_putstring
TESTED
'''
warnings.warn('deprecated', DeprecationWarning)
return self._call('db_putString', [db_name, key, value])
def db_getString(self, db_name, key):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#db_getstring
TESTED
'''
warnings.warn('deprecated', DeprecationWarning)
return self._call('db_getString', [db_name, key])
def db_putHex(self, db_name, key, value):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#db_puthex
TESTED
'''
if not value.startswith('0x'):
value = '0x{}'.format(value)
warnings.warn('deprecated', DeprecationWarning)
return self._call('db_putHex', [db_name, key, value])
def db_getHex(self, db_name, key):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#db_gethex
TESTED
'''
warnings.warn('deprecated', DeprecationWarning)
return self._call('db_getHex', [db_name, key])
def shh_version(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_version
N/A
'''
return self._call('shh_version')
def shh_post(self, topics, payload, priority, ttl, from_=None, to=None):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_post
NEEDS TESTING
'''
whisper_object = {
'from': from_,
'to': to,
'topics': topics,
'payload': payload,
'priority': hex(priority),
'ttl': hex(ttl),
}
return self._call('shh_post', [whisper_object])
def shh_newIdentity(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newidentity
N/A
'''
return self._call('shh_newIdentity')
def shh_hasIdentity(self, address):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_hasidentity
NEEDS TESTING
'''
return self._call('shh_hasIdentity', [address])
def shh_newGroup(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newgroup
N/A
'''
return self._call('shh_newGroup')
def shh_addToGroup(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_addtogroup
NEEDS TESTING
'''
return self._call('shh_addToGroup')
def shh_newFilter(self, to, topics):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newfilter
NEEDS TESTING
'''
_filter = {
'to': to,
'topics': topics,
}
return self._call('shh_newFilter', [_filter])
def shh_uninstallFilter(self, filter_id):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_uninstallfilter
NEEDS TESTING
'''
return self._call('shh_uninstallFilter', [filter_id])
def shh_getFilterChanges(self, filter_id):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getfilterchanges
NEEDS TESTING
'''
return self._call('shh_getFilterChanges', [filter_id])
def shh_getMessages(self, filter_id):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getmessages
NEEDS TESTING
'''
return self._call('shh_getMessages', [filter_id])
def getBlockRlp(self, number=0):
return self._call('debug_getBlockRlp', [number])
def traceTransaction(self, txHash):
return self._call('debug_traceTransaction', [txHash])

@ -0,0 +1,8 @@
BLOCK_TAG_EARLIEST = 'earliest'
BLOCK_TAG_LATEST = 'latest'
BLOCK_TAG_PENDING = 'pending'
BLOCK_TAGS = (
BLOCK_TAG_EARLIEST,
BLOCK_TAG_LATEST,
BLOCK_TAG_PENDING,
)

@ -0,0 +1,18 @@
class EthJsonRpcError(Exception):
pass
class ConnectionError(EthJsonRpcError):
pass
class BadStatusCodeError(EthJsonRpcError):
pass
class BadJsonError(EthJsonRpcError):
pass
class BadResponseError(EthJsonRpcError):
pass

@ -0,0 +1,38 @@
from ethjsonrpc.constants import BLOCK_TAGS
def hex_to_dec(x):
'''
Convert hex to decimal
'''
return int(x, 16)
def clean_hex(d):
'''
Convert decimal to hex and remove the "L" suffix that is appended to large
numbers
'''
return hex(d).rstrip('L')
def validate_block(block):
if isinstance(block, basestring):
if block not in BLOCK_TAGS:
raise ValueError('invalid block tag')
if isinstance(block, int):
block = hex(block)
return block
def wei_to_ether(wei):
'''
Convert wei to ether
'''
return 1.0 * wei / 10**18
def ether_to_wei(ether):
'''
Convert ether to wei
'''
return ether * 10**18

@ -0,0 +1,57 @@
from setuptools import setup, find_packages
from codecs import open
from os import path
here = path.abspath(path.dirname(__file__))
try:
import pypandoc
long_description = pypandoc.convert('README.md', 'rst')
except(IOError, ImportError):
long_description = open('README.md').read()
setup(
name='mythril',
version='0.1.0',
description='Mythril is an assembler and disassembler for Ethereum VM bytecode',
long_description=long_description,
url='https://github.com/b-mueller/mythril',
author='Bernhard Mueller',
license='MIT',
classifiers=[
'Development Status :: 3 - Alpha',
'Intended Audience :: Science/Research',
'Topic :: Software Development :: Disassemblers',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
],
keywords='hacking disassmbler ethereum',
packages=find_packages(exclude=['contrib', 'docs', 'tests']),
install_requires=[
'ethereum==2.0.4',
],
extras_require={
},
scripts=['mythril']
)
Loading…
Cancel
Save