CODE: CLI Refactoring

Submission 522596 by nowind_lee to the challenge
http://www.topcoder.com/challenges/30063470
pull/81/head
Dr. Sergey Pogodin 7 years ago
parent 226aecff14
commit f1430a8c3e
  1. 4
      Dockerfile
  2. 3
      myth
  3. 668
      mythril/ipc/client.py
  4. 48
      mythril/ipc/utils.py
  5. 644
      mythril/rpc/base_client.py
  6. 635
      mythril/rpc/client.py
  7. 9
      requirements.txt
  8. 1
      setup.py

@ -4,7 +4,7 @@ COPY . .
RUN apt-get update \
&& apt-get install -y software-properties-common python-software-properties \
&& add-apt-repository ppa:ethereum/ethereum \
&& add-apt-repository -y ppa:ethereum/ethereum \
&& apt-get update \
&& apt-get install -y solc \
&& apt-get install -y libssl-dev \
@ -13,7 +13,7 @@ RUN apt-get update \
&& pip3 install --upgrade pip \
&& apt-get install -y pandoc \
&& apt-get install -y git \
&& pip3 install laser-ethereum \
&& pip3 install -r requirements.txt \
&& python setup.py install
CMD []

@ -20,7 +20,6 @@ from mythril.analysis.callgraph import generate_graph
from mythril.analysis.security import fire_lasers
from mythril.analysis.report import Report
from laser.ethereum import helper
from web3 import Web3
from ethereum import utils
from pathlib import Path
from json.decoder import JSONDecodeError
@ -340,7 +339,7 @@ if args.storage:
if array:
position_formated = str(position).zfill(64)
position = int(Web3.sha3(position_formated), 16)
position = int(utils.sha3(position_formated), 16)
try:
if length == 1:

@ -1,633 +1,71 @@
import json
import warnings
import socket
from ethereum import utils
from ethereum.abi import encode_abi, decode_abi
from web3 import Web3, IPCProvider
#HTTPProvider,
from mythril.rpc.base_client import BaseClient
from .utils import (get_default_ipc_path, to_text, to_bytes)
from .constants import BLOCK_TAGS, BLOCK_TAG_LATEST
from .utils import hex_to_dec, clean_hex, validate_block
from .exceptions import (ConnectionError, BadStatusCodeError,
BadJsonError, BadResponseError)
IPC_PATH = None
try:
from json import JSONDecodeError
except ImportError:
JSONDecodeError = ValueError
IPC_PATH = None
'''
This code is adapted from: https://github.com/ConsenSys/ethjsonrpc
This code is mostly adapted from:
- https://github.com/ConsenSys/ethjsonrpc
- https://github.com/pipermerriam/ethereum-ipc-client
- https://github.com/ethereum/web3.py
'''
class EthIpc(object):
'''
Ethereum IPC client class using web3.py
'''
web3 = Web3(IPCProvider())
DEFAULT_GAS_PER_TX = 90000
DEFAULT_GAS_PRICE = 50 * 10**9 # 50 gwei
def __init__(self, ipc_path=IPC_PATH):
#not used so far
self.ipc_path = ipc_path
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.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 IPC server, without sending a
transaction (useful for reading data)
'''
data = self._encode_function(sig, args)
data_hex = data.encode('hex')
# could be made to use web3py directly, but instead uses eth_call which is adapted
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
http://web3py.readthedocs.io/en/latest/web3.version.html#web3.version.Version.node
'''
return self.web3.version.node
def web3_sha3(self, data):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#web3_sha3
http://web3py.readthedocs.io/en/latest/overview.html#Web3.sha3
Encoding probably not necessary
'''
data = str(data).encode('hex')
return self.web3.sha3(data)
def net_version(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#net_version
http://web3py.readthedocs.io/en/latest/web3.version.html#web3.version.Version.network
'''
return self.web3.version.network
def net_listening(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#net_listening
Only indirectly available
'''
return self.web3net.listening()
def net_peerCount(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#net_peercount
ONLY indirectly available
'''
return self.web3.net.peerCount()
def eth_protocolVersion(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_protocolversion
http://web3py.readthedocs.io/en/latest/web3.version.html?highlight=net#web3.version.Version.ethereum
'''
return self.web3.version.ethereum
def eth_syncing(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_syncing
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=syncing#web3.eth.Eth.syncing
'''
return self.web3.eth.syncing
def eth_coinbase(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_coinbase
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=syncing#web3.eth.Eth.coinbase
'''
return self.web3.eth.coinbase
def eth_mining(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_mining
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=syncing#web3.eth.Eth.mining
'''
return self.web3.Eth.mining
def eth_hashrate(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_hashrate
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=syncing#web3.eth.Eth.hashrate
'''
return web3.eth.hashrate
def eth_gasPrice(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gasprice
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.gasPrice
'''
return web3.eth.gasPrice
def eth_accounts(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_accounts
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.accounts
'''
return self.web3.eth.accounts
def eth_blockNumber(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_blocknumber
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.blockNumber
'''
return self.web3.eth.blockNumber
def eth_getBalance(self, address=None, block=BLOCK_TAG_LATEST):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getbalance
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.getBalance
'''
address = address or self.eth_coinbase()
block = validate_block(block)
return self.web3.eth.getBalance(address, block_identifier=block)
def eth_getStorageAt(self, address=None, position=0, block=BLOCK_TAG_LATEST):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getstorageat
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.getStorageAt
'''
block = validate_block(block)
return self.web3.eth.getStorageAt(address, position, block_identifier=block)
def eth_getTransactionCount(self, address, block=BLOCK_TAG_LATEST):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactioncount
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.getTransactionCount
'''
block = validate_block(block)
return self.web3.eth.getTransactionCount(address, block_identifier=block)
def eth_getBlockTransactionCountByHash(self, block_hash):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblocktransactioncountbyhash
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.getBlockTransactionCount
class EthIpc(BaseClient):
'''
return self.web3.eth.getBlockTransactionCount(block_hash)
def eth_getBlockTransactionCountByNumber(self, block=BLOCK_TAG_LATEST):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblocktransactioncountbynumber
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.getBlockTransactionCount
'''
block = validate_block(block)
return self.web3.eth.getBlockTransactionCount(block)
def eth_getUncleCountByBlockHash(self, block_hash):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclecountbyblockhash
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.getUncle
(not implemented with convenience functions)
'''
return self.web3.manager.request_blocking('eth_getUncleCountByBlockHash', [block_hash])
return self.web3.eth.getUncleCount(block_hash)
def eth_getUncleCountByBlockNumber(self, block=BLOCK_TAG_LATEST):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclecountbyblocknumber
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.getUncle
'''
block = validate_block(block)
self.web3.manager.request_blocking('debug_getBlockRlp', [number])
return self.web3.eth.getUncleCount(block)
def eth_getCode(self, address, default_block=BLOCK_TAG_LATEST):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getcode
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.getCode
'''
if isinstance(default_block, str):
if default_block not in BLOCK_TAGS:
raise ValueError
return self.web3.eth.getCode(address, block_identifier=default_block)
def eth_sign(self, address, data):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.sign
either data= hexstr= or text= probably not needed now but if used should be differentiated
'''
return self.web3.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
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=syncing#web3.eth.Eth.sendTransaction
'''
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.web3.eth.sendTransaction(params)
def eth_sendRawTransaction(self, data):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendrawtransaction
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=syncing#web3.eth.Eth.sendRawTransaction
'''
return self.web3.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
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=syncing#web3.eth.Eth.call
'''
if isinstance(default_block, str):
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.web3.eth.call(obj, block_identifier=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
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.estimateGas
'''
if isinstance(default_block, str):
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 self.web3.eth.estimateGas(obj)
def eth_getBlockByHash(self, block_hash, tx_objects=True):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbyhash
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.getBlock
'''
return self.web3.eth.getBlock(block_identifier=block_hash, full_transactions=tx_objects)
def eth_getBlockByNumber(self, block=BLOCK_TAG_LATEST, tx_objects=True):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbynumber
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.getBlock
'''
block = validate_block(block)
return self.web3.eth.getBlock(block_identifier=block, full_transactions=tx_objects)
def eth_getTransactionByHash(self, tx_hash):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyhash
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.getTransaction
'''
return self.web3.eth.getTransactionByHash(tx_hash)
def eth_getTransactionByBlockHashAndIndex(self, block_hash, index=0):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyblockhashandindex
http://web3py.readthedocs.io/en/latest/web3.eth.html#web3.eth.Eth.getTransactionFromBlock
'''
return self.web3.eth.getTransactionFromBlock(block_identifier=block_hash, transaction_index=index)
def eth_getTransactionByBlockNumberAndIndex(self, block=BLOCK_TAG_LATEST, index=0):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyblocknumberandindex
http://web3py.readthedocs.io/en/latest/web3.eth.html#web3.eth.Eth.getTransactionFromBlock
'''
block = validate_block(block)
return self.web3.eth.getTransactionFromBlock(block_identifier=block, transaction_index=index)
def eth_getTransactionReceipt(self, tx_hash):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionreceipt
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=gasprice#web3.eth.Eth.getTransactionReceipt
'''
return self.web3.eth.getTransactionReceipt(tx_hash)
def eth_getUncleByBlockHashAndIndex(self, block_hash, index=0):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclebyblockhashandindex
Indirectly accessible
self.web3.manager.request_blocking('rpc/ipc function', [params])
'''
return self.web3.manager.request_blocking('eth_getUncleByBlockHashAndIndex', [block_hash, web3.toHex(index)])
def eth_getUncleByBlockNumberAndIndex(self, block=BLOCK_TAG_LATEST, index=0):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclebyblocknumberandindex
Indirectly accessible
'''
block = validate_block(block)
return self.web3.manager.request_blocking('eth_getUncleByBlockNumberAndIndex', [block, web3.toHex(index)])
def eth_getCompilers(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getcompilers
Indirectly implemented
'''
return self.web3.manager.request_blocking('eth_getCompilers')
def eth_compileSolidity(self, code):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compilesolidity
Indirectly implemented
'''
return self.web3.manager.request_blocking('eth_compileSolidity', [code])
def eth_compileLLL(self, code):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compilelll
Indirectly accessible
'''
return self.web3.manager.request_blocking('eth_compileLLL', [code])
def eth_compileSerpent(self, code):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compileserpent
Indirectly implemented
'''
return self.web3.manager.request_blocking('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
http://web3py.readthedocs.io/en/latest/web3.eth.html#web3.eth.Eth.filter
'''
filter_params = {
'fromBlock': from_block,
'toBlock': to_block,
'address': address,
'topics': topics,
}
return self.web3.eth.newFilter(filter_params)
def eth_newBlockFilter(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newblockfilter
http://web3py.readthedocs.io/en/latest/web3.eth.html#web3.eth.Eth.filter
'''
return self.web3.eth.newFilter('latest')
def eth_newPendingTransactionFilter(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newpendingtransactionfilter
http://web3py.readthedocs.io/en/latest/web3.eth.html#web3.eth.Eth.filter
'''
return self.web3.eth.newFilter('pending')
def eth_uninstallFilter(self, filter_id):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_uninstallfilter
http://web3py.readthedocs.io/en/latest/web3.eth.html#web3.eth.Eth.uninstallFilter
'''
return self.web3.eth.uninstallFilter(filter_id)
def eth_getFilterChanges(self, filter_id):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterchanges
http://web3py.readthedocs.io/en/latest/web3.eth.html#web3.eth.Eth.getFilterChanges
'''
return self.web3.eth.getFilterChanges(filter_id)
def eth_getFilterLogs(self, filter_id):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterlogs
http://web3py.readthedocs.io/en/latest/web3.eth.html#web3.eth.Eth.getFilterLogs
'''
return self.web3.eth.getFilterLogs(filter_id)
def eth_getLogs(self, filter_object):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs
http://web3py.readthedocs.io/en/latest/filters.html?highlight=getLogs#web3.utils.filters.LogFilter.get
'''
return self.filter_object.get()
def eth_getWork(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getwork
http://web3py.readthedocs.io/en/latest/releases.html?highlight=getWork#id15
'''
return self.web3.eth.getWork()
def eth_submitWork(self, nonce, header, mix_digest):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_submitwork
Implemented indirectly
'''
return self.web3.manager.request_blocking('eth_submitWork', [nonce, header, mix_digest])
def eth_submitHashrate(self, hash_rate, client_id):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_submithashrate
Implemented indirectly
'''
return self.web3.manager.request_blocking('eth_submitHashrate', [hash_rate, client_id])
def shh_version(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_version
http://web3py.readthedocs.io/en/latest/web3.shh.html#web3.shh.Shh.version
'''
return self.web3.shh.version()
def shh_post(self, topics, payload, priority, ttl, from_=None, to=None):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_post
http://web3py.readthedocs.io/en/latest/web3.shh.html#web3.shh.Shh.post
# only topics and payload are necessary according to web3.py
'''
whisper_object = {
'from': from_,
'to': to,
'topics': web3.toHex(topics),
'payload': web3.toHex(payload),
'priority': web3.toHex(priority),
'ttl': web3.toHex(ttl)
}
return self.web3.shh.post(whisper_object)
def shh_newIdentity(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newidentity
http://web3py.readthedocs.io/en/latest/web3.shh.html#web3.shh.Shh.newIdentity
'''
return self.web3.shh.newIdentity()
def shh_hasIdentity(self, address):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_hasidentity
http://web3py.readthedocs.io/en/latest/web3.shh.html#web3.shh.Shh.hasIdentity
'''
return self.web3.shh.hasIdentity(address)
def shh_newGroup(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newgroup
http://web3py.readthedocs.io/en/latest/web3.shh.html#web3.shh.Shh.newGroup
'''
return self.web3.shh.newGroup()
def shh_addToGroup(self):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_addtogroup
http://web3py.readthedocs.io/en/latest/web3.shh.html#web3.shh.Shh.addToGroup
'''
return self.web3.shh.addToGroup()
def shh_newFilter(self, to, topics):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newfilter
http://web3py.readthedocs.io/en/latest/web3.shh.html#web3.shh.Shh.filter
# to is optional
'''
_filter = {
'topics': topics,
'to': to
def __init__(self, ipc_path=IPC_PATH, testnet=False):
if ipc_path is None:
ipc_path = get_default_ipc_path(testnet)
self.ipc_path = ipc_path
self._socket = self.get_socket()
def get_socket(self):
_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
_socket.connect(self.ipc_path)
# Tell the socket not to block on reads.
_socket.settimeout(2)
return _socket
def _call(self, method, params=None, _id=1):
params = params or []
data = {
'jsonrpc': '2.0',
'method': method,
'params': params,
'id': _id,
}
return self.web3.shh.newFilter(_filter)
def shh_uninstallFilter(self, filter_id):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_uninstallfilter
http://web3py.readthedocs.io/en/latest/web3.shh.html#web3.shh.Shh.uninstallFilter
'''
return self.web3.shh.uninstallFilter(filter_id)
def shh_getFilterChanges(self, filter_id):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getfilterchanges
http://web3py.readthedocs.io/en/latest/web3.eth.html?highlight=syncing#web3.eth.Eth.getFilterChanges
'''
filt = self.web3.eth.filter()
return self.web3.shh.getFilterChanges(filter_id)
request = to_bytes(json.dumps(data))
def shh_getMessages(self, filter_id):
'''
https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getmessages
http://web3py.readthedocs.io/en/latest/web3.shh.html#web3.shh.Shh.getMessages
'''
return self.web3.shh.getMessages(filter_id)
for _ in range(3):
self._socket.sendall(request)
response_raw = ""
def getBlockRlp(self, number=0):
while True:
try:
response_raw += to_text(self._socket.recv(4096))
except socket.timeout:
break
#not accessible with convenience functions
if response_raw == "":
self._socket.close()
self._socket = self.get_socket()
continue
return self.web3.manager.request_blocking('debug_getBlockRlp', [number])
break
else:
raise ValueError("No JSON returned by socket")
def traceTransaction(self, txHash):
#atm not directly accessible, so something like this is needed
#https://github.com/pipermerriam/web3.py/issues/308
response = json.loads(response_raw)
return self.web3.manager.request_blocking('debug_traceTransaction', [txHash])
if "error" in response:
raise ValueError(response["error"]["message"])
return response["result"]

@ -1,3 +1,6 @@
import os
import sys
from .constants import BLOCK_TAGS
@ -7,6 +10,11 @@ def hex_to_dec(x):
'''
return int(x, 16)
def to_bytes(text):
return text.encode('utf-8')
def to_text(byte_array):
return byte_array.decode('utf-8')
def clean_hex(d):
'''
@ -36,3 +44,43 @@ def ether_to_wei(ether):
Convert ether to wei
'''
return ether * 10**18
def get_default_ipc_path(testnet=False):
if testnet:
testnet = "testnet"
else:
testnet = ""
if sys.platform == 'darwin':
ipc_path = os.path.expanduser(os.path.join("~", "Library", "Ethereum", testnet, "geth.ipc"))
if os.path.exists(ipc_path):
return ipc_path
ipc_path = os.path.expanduser(os.path.join("~", "Library", "Application Support", "io.parity.ethereum", "jsonrpc.ipc"))
if os.path.exists(ipc_path):
return ipc_path
elif sys.platform.startswith('linux'):
ipc_path = os.path.expanduser(os.path.join("~", ".ethereum", testnet, "geth.ipc"))
if os.path.exists(ipc_path):
return ipc_path
ipc_path = os.path.expanduser(os.path.join("~", ".local", "share", "io.parity.ethereum", "jsonrpc.ipc"))
if os.path.exists(ipc_path):
return ipc_path
elif sys.platform == 'win32':
ipc_path = os.path.join("\\\\", ".", "pipe", "geth.ipc")
if os.path.exists(ipc_path):
return ipc_path
ipc_path = os.path.join("\\\\", ".", "pipe", "jsonrpc.ipc")
if os.path.exists(ipc_path):
return ipc_path
else:
raise ValueError(
"Unsupported platform '{0}'. Only darwin/linux2/win32 are "
"supported. You must specify the ipc_path".format(sys.platform)
)

@ -0,0 +1,644 @@
from abc import (abstractmethod)
from ethereum.abi import encode_abi, decode_abi
from ethereum import utils
from .constants import BLOCK_TAGS, BLOCK_TAG_LATEST
from .utils import hex_to_dec, clean_hex, validate_block
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 BaseClient(object):
@abstractmethod
def _call(self, method, params=None, _id=1):
pass
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.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, str):
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, str):
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, str):
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 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])

@ -3,13 +3,8 @@ import json
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 .constants import BLOCK_TAGS, BLOCK_TAG_LATEST
from .utils import hex_to_dec, clean_hex, validate_block
from .exceptions import (ConnectionError, BadStatusCodeError,
BadJsonError, BadResponseError)
from .exceptions import (ConnectionError, BadStatusCodeError, BadJsonError, BadResponseError)
from .base_client import BaseClient
GETH_DEFAULT_RPC_PORT = 8545
ETH_DEFAULT_RPC_PORT = 8545
@ -21,14 +16,11 @@ JSON_MEDIA_TYPE = 'application/json'
'''
This code is adapted from: https://github.com/ConsenSys/ethjsonrpc
'''
class EthJsonRpc(object):
class EthJsonRpc(BaseClient):
'''
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
@ -65,624 +57,3 @@ class EthJsonRpc(object):
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.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, str):
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, str):
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, str):
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 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])

@ -1,8 +1,15 @@
ethereum>=2.0.4
ZODB>=5.3.0
z3-solver>=4.5
web3
laser-ethereum==0.5.9
requests
BTrees
py-solc
eth_abi>=1.0.0
eth-utils>=1.0.1
eth-account>=0.1.0a2
eth-hash>=0.1.0
eth-keyfile>=0.5.1
eth-keys>=0.2.0b3
eth-rlp>=0.1.0
eth-tester>=0.1.0b21

@ -288,7 +288,6 @@ setup(
install_requires=[
'ethereum>=2.0.4',
'web3',
'ZODB>=5.3.0',
'z3-solver>=4.5',
'laser-ethereum==0.5.9',

Loading…
Cancel
Save