from rpc . client import EthJsonRpc
from ethcontract import ETHContract
from tinydb import TinyDB , Query
import codecs
import hashlib
class ContractStorage :
def __init__ ( self ) :
self . db = TinyDB ( ' ./contracts.json ' )
def initialize ( self , rpchost , rpcport ) :
eth = EthJsonRpc ( rpchost , rpcport )
blockNum = eth . eth_blockNumber ( )
while ( blockNum > 0 ) :
if not blockNum % 1000 :
print ( " Processing block: " + str ( blockNum ) )
block = eth . eth_getBlockByNumber ( blockNum )
for tx in block [ ' transactions ' ] :
if not tx [ ' to ' ] :
receipt = eth . eth_getTransactionReceipt ( tx [ ' hash ' ] )
contract_address = receipt [ ' contractAddress ' ]
contract_code = eth . eth_getCode ( contract_address )
m = hashlib . md5 ( )
m . update ( contract_code . encode ( ' UTF-8 ' ) )
contract_hash = codecs . encode ( m . digest ( ) , ' hex_codec ' )
contract_id = contract_hash . decode ( " utf-8 " )
contract_balance = eth . eth_getBalance ( contract_address )
Contract = Query ( )
new_instance = { ' address ' : contract_address , ' balance ' : contract_balance }
s = self . db . search ( Contract . id == contract_id )
if not len ( s ) :
self . db . insert ( { ' id ' : contract_id , ' code ' : contract_code , ' instances ' : [ new_instance ] } )
else :
instances = s [ 0 ] [ ' instances ' ]
instances . append ( new_instance )
self . db . update ( { ' instances ' : instances } , Contract . id == contract_id )
blockNum - = 1
def get_contract_code_by_address ( self , address ) :
Contract = Query ( )
Instance = Query ( )
ret = self . db . search ( Contract . instances . any ( Instance . address == address ) )
return ret [ 0 ] [ ' code ' ]
def search ( self , expression ) :
all_contracts = self . db . all ( )
for c in all_contracts :
for instance in c [ ' instances ' ] :
if ( ' balance ' in instance ) :
contract = ETHContract ( c [ ' code ' ] , instance [ ' balance ' ] )
if ( contract . matches_expression ( expression ) ) :
print ( " Found contract: " + instance [ ' address ' ] )