From aa96623e352fe096b6679cc3ea10ef62a260a711 Mon Sep 17 00:00:00 2001 From: tintinweb Date: Wed, 4 Jul 2018 20:11:09 +0200 Subject: [PATCH] add custom exception for online lookup expose timeout/proxies arguments for the online lookup ignore missing signatures in abi.json fix example version bump --- ethereum_input_decoder/__main__.py | 8 ++++--- ethereum_input_decoder/decoder.py | 37 ++++++++++++++++++++++-------- setup.py | 4 ++-- test/example.py | 8 +++---- 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/ethereum_input_decoder/__main__.py b/ethereum_input_decoder/__main__.py index d8aeef7..13f0f32 100644 --- a/ethereum_input_decoder/__main__.py +++ b/ethereum_input_decoder/__main__.py @@ -1,9 +1,11 @@ # -*- coding: UTF-8 -*- -from ethereum_input_decoder import ContractAbi,AbiMethod, Utils +import sys +import os import argparse import json -import sys, os +from ethereum_input_decoder import ContractAbi,AbiMethod, Utils + def main(): parser = argparse.ArgumentParser(description='Ethereum Input decoder') @@ -58,4 +60,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/ethereum_input_decoder/decoder.py b/ethereum_input_decoder/decoder.py index 5ee68eb..edd1424 100644 --- a/ethereum_input_decoder/decoder.py +++ b/ethereum_input_decoder/decoder.py @@ -8,6 +8,18 @@ import requests +class InputDecoderException(Exception): + pass + + +class FourByteDirectoryException(InputDecoderException): + pass + + +class FourByteDirectoryOnlineLookupError(FourByteDirectoryException): + pass + + class Utils: @staticmethod @@ -38,20 +50,24 @@ def parse_text_signature(text_signature): 'outputs': []} @staticmethod - def lookup_signatures(sighash): - resp = requests.get("https://www.4byte.directory/api/v1/signatures/?hex_signature=%s" % sighash).json() - for sig in resp["results"]: - yield sig["text_signature"] + def lookup_signatures(sighash, timeout=None, proxies=None): + try: + resp = requests.get("https://www.4byte.directory/api/v1/signatures/?hex_signature=%s" % sighash, + timeout=timeout, proxies=proxies).json() + for sig in resp["results"]: + yield sig["text_signature"] + except (requests.exceptions.RequestException) as re: + raise FourByteDirectoryOnlineLookupError(re) @staticmethod - def get_pseudo_abi_for_sighash(sighash): - for text_signature in FourByteDirectory.lookup_signatures(sighash): + def get_pseudo_abi_for_sighash(sighash, timeout=None, proxies=None): + for text_signature in FourByteDirectory.lookup_signatures(sighash, timeout=timeout, proxies=proxies): pseudo_abi = FourByteDirectory.parse_text_signature(text_signature) pseudo_abi['signature'] = sighash yield pseudo_abi @staticmethod - def get_pseudo_abi_for_input(s): + def get_pseudo_abi_for_input(s, timeout=None, proxies=None): """ Lookup sighash from 4bytes.directory, create a pseudo api and try to decode it with the parsed abi. May return multiple results as sighashes may collide. @@ -59,7 +75,7 @@ def get_pseudo_abi_for_input(s): :return: pseudo abi for method """ sighash = Utils.bytes_to_str(s[:4]) - for pseudo_abi in FourByteDirectory.get_pseudo_abi_for_sighash(sighash): + for pseudo_abi in FourByteDirectory.get_pseudo_abi_for_sighash(sighash, timeout=timeout, proxies=proxies): types = [ti["type"] for ti in pseudo_abi['inputs']] try: # test decoding @@ -98,7 +114,10 @@ def _prepare_abi(self, jsonabi): abi_e.setdefault("inputs", []) self.signatures[b"__fallback__"] = abi_e elif abi_e["type"] == "function": - self.signatures[Utils.str_to_bytes(abi_e["signature"])] = abi_e + # function and signature present + # todo: we could generate the sighash ourselves? requires keccak256 + if abi_e.get("signature"): + self.signatures[Utils.str_to_bytes(abi_e["signature"])] = abi_e elif abi_e["type"] == "event": self.signatures[b"__event__"] = abi_e else: diff --git a/setup.py b/setup.py index 92e7b35..7b28722 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ def read(fname): setup( name="ethereum_input_decoder", - version="0.2.1", + version="0.2.2", packages=["ethereum_input_decoder"], author="tintinweb", author_email="tintinweb@oststrom.com", @@ -18,7 +18,7 @@ def read(fname): license="GPLv3", keywords=["ethereum", "blockchain", "input", "transaction", "decoder"], url="https://github.com/tintinweb/ethereum-input-decoder/", - download_url="https://github.com/tintinweb/ethereum-input-decoder/tarball/v0.2.1", + download_url="https://github.com/tintinweb/ethereum-input-decoder/tarball/v0.2.2", #python setup.py register -r https://testpypi.python.org/pypi long_description=read("README.rst") if os.path.isfile("README.rst") else read("README.md"), install_requires=["eth-abi", "requests"], diff --git a/test/example.py b/test/example.py index e7e6c4e..3c3d35c 100644 --- a/test/example.py +++ b/test/example.py @@ -1,4 +1,4 @@ -from ethereum_input_decoder import ContractAbi +from ethereum_input_decoder import ContractAbi, Utils import json if __name__ == "__main__": @@ -11,13 +11,13 @@ # This is the constructor arguments: # https://etherscan.io/address/0xab7c74abc0c4d48d1bdad5dcb26153fc8780f83e#code - print(ca.describe_constructor(ContractAbi.str_to_bytes( + print(ca.describe_constructor(Utils.str_to_bytes( "000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000002903cadbe271e057edef157340b52a5898d7424f000000000000000000000000ba7ca1bcf210c1b37cf5818816c4a819c3040ea700000000000000000000000014cd6536d449e3f6878f2d6859e1ff92ae0990e60000000000000000000000000c24441e42277445e38e02dfc3494577c05ba46b"))) # constructor None ((address[]) _owners = ('0x2903cadbe271e057edef157340b52a5898d7424f', '0xba7ca1bcf210c1b37cf5818816c4a819c3040ea7', '0x14cd6536d449e3f6878f2d6859e1ff92ae0990e6', '0x0c24441e42277445e38e02dfc3494577c05ba46b'), (uint256) _required = 2, (uint256) _daylimit = 1000000000000000000) returns () # This is one input transaction: # https://www.etherchain.org/tx/1e9ed6236afb884fe7cad9a807886ba61b9e9a2fc944a991e3e8725d2158c7b2 - print(ca.describe_input(ContractAbi.str_to_bytes( - "0x797af62798d790d3133e0049215669e09b55a0b59d586c95f94c2d56b2812040133d7707"))) + print(ca.describe_input(Utils.str_to_bytes( + "0xfedd60920000000000000000000000000595d187cac88f04466371eff3a6b6d1b12fb013b92dd9476601c067bcd9730c83d54263fbc0da1c2c01f05a834199427aa3fad40000000000000000000000005c3766a9a906aa17e16dbbdaac0c93d41c0d057f"))) # f \ No newline at end of file