ethd-gas-sum/eth_gas_sum/runnable/sum.py

149 lines
5.0 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# standard imports
import logging
# external imports
import chainlib.eth.cli
from chainlib.chain import ChainSpec
from chainsyncer.backend.file import FileBackend
from chainlib.interface import ChainInterface
from chainlib.eth.block import (
block_latest,
block_by_number,
Block,
)
from chainlib.eth.tx import (
receipt,
Tx,
)
from chainsyncer.driver.history import HistorySyncer
from chainsyncer.driver.head import HeadSyncer
from hexathon import (
strip_0x,
uniform as hex_uniform,
)
logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger()
arg_flags = chainlib.eth.cli.argflag_std_read
argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
argparser.add_argument('--start', type=int, help='start at block')
argparser.add_argument('--end', type=int, help='end block (not inclusive)')
argparser.add_argument('--interval', type=int, default=5, help='syncer poll interval for new blocks')
argparser.add_argument('-d', type=str, required=True, help='output directory')
argparser.add_argument('--sender', type=str, action='append', default=[], help='sender address sender to monitor')
argparser.add_argument('--recipient', type=str, action='append', default=[], help='recipient address sender to monitor')
argparser.add_argument('--address', type=str, action='append', default=[], help='sender or recipient address to monitor')
args = argparser.parse_args()
extra_args = {
'start': None,
'end': None,
'address': None,
'sender': None,
'recipient': None,
'd': '_OUTPUT_DIR',
'interval': 'SYNCER_LOOP_INTERVAL',
}
# process config
config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args)
logg.debug('config loaded\n'+ str(config))
# set up rpc
rpc = chainlib.eth.cli.Rpc()
conn = rpc.connect_by_config(config)
chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
class EthChainInterface(ChainInterface):
def __init__(self):
self._block_by_number = block_by_number
self._block_from_src = Block.from_src
self._tx_receipt = receipt
self._src_normalize = Tx.src_normalize
class GasAddFilter:
def __init__(self, chain_spec, senders, recipients):
self.senders = senders
self.recipients = recipients
self.tx_gas = {}
self.gas_sum = 0
self.match_label = None
if len(senders) == 0 and len(recipients) == 0:
self.match_label = 'match'
def filter(self, conn, block, tx, db_session):
sender = hex_uniform(strip_0x(tx.outputs[0]))
recipient = hex_uniform(strip_0x(tx.inputs[0]))
match_label = self.match_label
if match_label == None:
if sender in self.senders:
match_label = 'sender ' + sender
elif recipient in self.recipients:
match_label = 'recipient ' + receipient
self.gas_sum += tx.gas_used
self.tx_gas[tx.hash] = tx.gas_used
logg.info('{} tx {} ({}/{}) gas {} new sum {}'.format(match_label, tx.hash, tx.block.number, tx.index, tx.gas_used, self.gas_sum))
def sum(self):
return self.gas_sum
def main():
loop_interval = config.get('SYNCER_LOOP_INTERVAL')
start = config.get('_START')
if start == None:
o = block_latest()
r = conn.do(o)
block_current = int(r, 16)
start = block_current + 1
end = config.get('_END')
syncer = None
chain_interface = EthChainInterface()
if end != None:
backend = FileBackend.initial(chain_spec, end, start_block_height=start, base_dir=config.get('_OUTPUT_DIR'))
syncer = HistorySyncer(backend, chain_interface)
else:
backend = FileBackend.live(chain_spec, start, base_dir=config.get('_OUTPUT_DIR'))
syncer = HeadSyncer(backend, chain_interface)
senders = []
recipients = []
for address in config.get('_SENDER'):
clean_address = hex_uniform(strip_0x(address))
senders.append(clean_address)
logg.debug('monitoring sender {}'.format(clean_address))
for address in config.get('_RECIPIENT'):
clean_address = hex_uniform(strip_0x(address))
recipients.append(clean_address)
logg.debug('monitoring recipient {}'.format(clean_address))
for address in config.get('_ADDRESS'):
clean_address = hex_uniform(strip_0x(address))
if address not in senders:
senders.append(clean_address)
logg.debug('monitoring sender {}'.format(clean_address))
if address not in recipients:
recipients.append(clean_address)
logg.debug('monitoring recipient {}'.format(clean_address))
gas_filter = GasAddFilter(chain_spec, senders, recipients)
syncer.add_filter(gas_filter)
r = syncer.loop(config.get('SYNCER_LOOP_INTERVAL'), conn)
for k in gas_filter.tx_gas.keys():
print('tx {} gas {}'.format(k, gas_filter.tx_gas[k]))
print('total gas: ' + str(gas_filter.sum()))
if __name__ == '__main__':
main()