sum.py (5081B)
1 # standard imports 2 import logging 3 4 # external imports 5 import chainlib.eth.cli 6 from chainlib.chain import ChainSpec 7 from chainsyncer.backend.file import FileBackend 8 from chainlib.interface import ChainInterface 9 from chainlib.eth.block import ( 10 block_latest, 11 block_by_number, 12 Block, 13 ) 14 from chainlib.eth.tx import ( 15 receipt, 16 Tx, 17 ) 18 from chainsyncer.driver.history import HistorySyncer 19 from chainsyncer.driver.head import HeadSyncer 20 from hexathon import ( 21 strip_0x, 22 uniform as hex_uniform, 23 ) 24 25 26 logging.basicConfig(level=logging.WARNING) 27 logg = logging.getLogger() 28 29 30 arg_flags = chainlib.eth.cli.argflag_std_read 31 argparser = chainlib.eth.cli.ArgumentParser(arg_flags) 32 argparser.add_argument('--start', type=int, help='start at block') 33 argparser.add_argument('--end', type=int, help='end block (not inclusive)') 34 argparser.add_argument('--interval', type=int, default=5, help='syncer poll interval for new blocks') 35 argparser.add_argument('-d', type=str, required=True, help='output directory') 36 argparser.add_argument('--sender', type=str, action='append', default=[], help='sender address sender to monitor') 37 argparser.add_argument('--recipient', type=str, action='append', default=[], help='recipient address sender to monitor') 38 argparser.add_argument('--address', type=str, action='append', default=[], help='sender or recipient address to monitor') 39 args = argparser.parse_args() 40 41 extra_args = { 42 'start': None, 43 'end': None, 44 'address': None, 45 'sender': None, 46 'recipient': None, 47 'd': '_OUTPUT_DIR', 48 'interval': 'SYNCER_LOOP_INTERVAL', 49 } 50 # process config 51 config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args) 52 logg.debug('config loaded\n'+ str(config)) 53 54 # set up rpc 55 rpc = chainlib.eth.cli.Rpc() 56 conn = rpc.connect_by_config(config) 57 58 chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC')) 59 60 61 class EthChainInterface(ChainInterface): 62 63 def __init__(self): 64 self._block_by_number = block_by_number 65 self._block_from_src = Block.from_src 66 self._tx_receipt = receipt 67 self._src_normalize = Tx.src_normalize 68 69 70 class GasAddFilter: 71 72 def __init__(self, chain_spec, senders, recipients): 73 self.senders = senders 74 self.recipients = recipients 75 self.tx_gas = {} 76 self.gas_sum = 0 77 self.match_label = None 78 if len(senders) == 0 and len(recipients) == 0: 79 self.match_label = 'match' 80 81 82 def filter(self, conn, block, tx, db_session): 83 sender = hex_uniform(strip_0x(tx.outputs[0])) 84 recipient = hex_uniform(strip_0x(tx.inputs[0])) 85 match_label = self.match_label 86 if match_label == None: 87 if sender in self.senders: 88 match_label = 'sender ' + sender 89 elif recipient in self.recipients: 90 match_label = 'recipient ' + receipient 91 self.gas_sum += tx.gas_used 92 self.tx_gas[tx.hash] = tx.gas_used 93 logg.info('{} tx {} ({}/{}) gas {} new sum {}'.format(match_label, tx.hash, tx.block.number, tx.index, tx.gas_used, self.gas_sum)) 94 95 def sum(self): 96 return self.gas_sum 97 98 99 def main(): 100 loop_interval = config.get('SYNCER_LOOP_INTERVAL') 101 start = config.get('_START') 102 if start == None: 103 o = block_latest() 104 r = conn.do(o) 105 block_current = int(r, 16) 106 start = block_current + 1 107 end = config.get('_END') 108 109 syncer = None 110 chain_interface = EthChainInterface() 111 if end != None: 112 backend = FileBackend.initial(chain_spec, end, start_block_height=start, base_dir=config.get('_OUTPUT_DIR')) 113 syncer = HistorySyncer(backend, chain_interface) 114 else: 115 backend = FileBackend.live(chain_spec, start, base_dir=config.get('_OUTPUT_DIR')) 116 syncer = HeadSyncer(backend, chain_interface) 117 118 senders = [] 119 recipients = [] 120 121 for address in config.get('_SENDER'): 122 clean_address = hex_uniform(strip_0x(address)) 123 senders.append(clean_address) 124 logg.debug('monitoring sender {}'.format(clean_address)) 125 for address in config.get('_RECIPIENT'): 126 clean_address = hex_uniform(strip_0x(address)) 127 recipients.append(clean_address) 128 logg.debug('monitoring recipient {}'.format(clean_address)) 129 for address in config.get('_ADDRESS'): 130 clean_address = hex_uniform(strip_0x(address)) 131 if address not in senders: 132 senders.append(clean_address) 133 logg.debug('monitoring sender {}'.format(clean_address)) 134 if address not in recipients: 135 recipients.append(clean_address) 136 logg.debug('monitoring recipient {}'.format(clean_address)) 137 138 gas_filter = GasAddFilter(chain_spec, senders, recipients) 139 syncer.add_filter(gas_filter) 140 141 r = syncer.loop(config.get('SYNCER_LOOP_INTERVAL'), conn) 142 for k in gas_filter.tx_gas.keys(): 143 print('tx {} gas {}'.format(k, gas_filter.tx_gas[k])) 144 print('total gas: ' + str(gas_filter.sum())) 145 146 147 if __name__ == '__main__': 148 main()