commit e6bb7a47713fc5a0cce748e56d453849d6dcc3fd
parent 56be976b857a13e2646939c2c493b2b732f55226
Author: lash <dev@holbrook.no>
Date:   Sun, 30 Jan 2022 19:44:03 +0000
Add renderer interface to out filter
Diffstat:
6 files changed, 60 insertions(+), 24 deletions(-)
diff --git a/MANIFEST.in b/MANIFEST.in
@@ -0,0 +1 @@
+include *requirements.txt eth_monitor/data/config/*
diff --git a/eth_monitor/data/config/chain.ini b/eth_monitor/data/config/chain.ini
@@ -0,0 +1,2 @@
+[chain]
+spec = evm:berlin:1:ethereum
diff --git a/config/syncer.ini b/eth_monitor/data/config/syncer.ini
diff --git a/eth_monitor/filters/out.py b/eth_monitor/filters/out.py
@@ -1,24 +1,45 @@
 # standard imports
 import sys
+import logging
 
 # local imports
 from .base import RuledFilter
 
+logg = logging.getLogger(__name__)
+
+
+# Interface defining the signature for renderer in OutFilter
+# return string after local transformation
+def apply_interface(c, s, chain_str, conn, block, tx, db_session=None):
+    pass
+
 
 class OutFilter(RuledFilter):
 
-    def __init__(self, writer=sys.stdout, renderers=[], rules_filter=None):
+    def __init__(self, chain_spec, writer=sys.stdout, renderers=[], rules_filter=None):
         super(OutFilter, self).__init__(rules_filter=rules_filter)
         self.w = writer
         self.renderers = renderers
         self.c = 0
+        self.chain_spec = chain_spec
+        self.chain_spec_str = str(chain_spec)
+
+
+    def filter(self, conn, block, tx, db_session=None):
+        s = None
+    
+        for renderer in self.renderers:
+            s = renderer.apply(self.c, s, self.chain_spec_str, conn, block, tx)
+            if s != None:
+                break
 
+        if s == None:
+            data = tx.payload
+            if len(data) > 8:
+                data = data[:8] + '...'
+            if len(data) > 0:
+                data = 'data {}'.format(data)
+            s = '{} {} {} {}'.format(self.c, block, tx, data)
 
-    def filter(self, con, block, tx, db_session=None):
-        data = tx.payload
-        if len(data) > 8:
-            data = data[:8] + '...'
-        if len(data) > 0:
-            data = 'data {}'.format(data)
-        self.w.write('{} {} {} {}\n'.format(self.c, block, tx, data))
+        self.w.write(s + '\n')
         self.c += 1
diff --git a/eth_monitor/runnable/sync.py b/eth_monitor/runnable/sync.py
@@ -5,6 +5,7 @@ import argparse
 import confini
 import logging
 import os
+import importlib
 
 # external imports
 from chainlib.chain import ChainSpec
@@ -38,12 +39,13 @@ if default_eth_provider == None:
 
 script_dir = os.path.realpath(os.path.dirname(__file__))
 exec_dir = os.path.realpath(os.getcwd())
-default_config_dir = os.environ.get('CONFINI_DIR', os.path.join(exec_dir, 'config'))
+#default_config_dir = os.environ.get('CONFINI_DIR', os.path.join(exec_dir, 'config'))
+base_config_dir = os.path.join(script_dir, '..', 'data', 'config')
 
 argparser = argparse.ArgumentParser('master eth events monitor')
 argparser.add_argument('-p', '--provider', dest='p', default=default_eth_provider, type=str, help='Web3 provider url (http only)')
-argparser.add_argument('-c', type=str, default=default_config_dir, help='config file')
-argparser.add_argument('-i', '--chain-spec', dest='i', type=str, default='evm:ethereum:1', help='Chain specification string')
+argparser.add_argument('-c', type=str, help='config file')
+argparser.add_argument('-i', '--chain-spec', dest='i', type=str, help='Chain specification string')
 argparser.add_argument('--offset', type=int, default=0, help='Start sync on this block')
 #argparser.add_argument('--until', type=int, default=0, help='Start sync on this block')
 argparser.add_argument('--head', action='store_true', help='Start at current block height (overrides --offset, assumes --keep-alive)')
@@ -54,6 +56,7 @@ argparser.add_argument('--include-default', dest='include_default', action='stor
 argparser.add_argument('--store-tx-data', dest='store_tx_data', action='store_true', help='Include all transaction data objects by default')
 argparser.add_argument('--store-block-data', dest='store_block_data', action='store_true', help='Include all block data objects by default')
 argparser.add_argument('--excludes-file', type=str, dest='excludes_file', help='Load exclude rules from file')
+argparser.add_argument('--renderer', type=str, action='append', help='Python modules to dynamically load for rendering of transaction output')
 argparser.add_argument('-f', '--filter', type=str, action='append', help='Add python module filter path')
 argparser.add_argument('--cache-dir', dest='cache_dir', type=str, help='Directory to store tx data')
 argparser.add_argument('--single', action='store_true', help='Execute a single sync, regardless of previous states')
@@ -67,7 +70,7 @@ elif args.v:
     logg.setLevel(logging.INFO)
 
 config_dir = args.c
-config = confini.Config(config_dir, os.environ.get('CONFINI_ENV_PREFIX'))
+config = confini.Config(base_config_dir, os.environ.get('CONFINI_ENV_PREFIX'), override_dirs=args.c)
 config.process()
 args_override = {
         'CHAIN_SPEC': getattr(args, 'i'),
@@ -181,7 +184,7 @@ def setup_cache_filter(rules_filter=None):
     return CacheFilter(rules_filter=rules_filter)
 
 
-def setup_backend_resume(chain_spec, block_offset, block_limit, state_dir, callback, sync_offset=0, skip_history=False):
+def setup_backend_resume(chain_spec, block_offset, block_limit, state_dir, callback, chain_interface, sync_offset=0, skip_history=False):
     syncers = []
     syncer_backends = FileBackend.resume(chain_spec, block_offset, base_dir=state_dir)
     if len(syncer_backends) == 0:
@@ -199,26 +202,26 @@ def setup_backend_resume(chain_spec, block_offset, block_limit, state_dir, callb
             logg.info('resuming sync session {}'.format(syncer_backend))
    
     for syncer_backend in syncer_backends:
-        syncers.append(HistorySyncer(syncer_backend, chain_interface, block_callback=RuledFilter.block_callback))
+        syncers.append(HistorySyncer(syncer_backend, chain_interface, block_callback=callback)) #RuledFilter.block_callback))
 
     syncer_backend = FileBackend.live(chain_spec, block_offset+1, base_dir=state_dir)
-    syncers.append(HeadSyncer(syncer_backend, chain_interface, block_callback=cache_filter.block_callback))
+    syncers.append(HeadSyncer(syncer_backend, chain_interface, block_callback=callback))
     return syncers  
 
 
 def setup_backend_single(chain_spec, block_offset, block_limit, state_dir, callback, chain_interface, sync_offset=0, skip_history=False):
     syncer_backend = FileBackend.initial(chain_spec, block_offset, start_block_height=sync_offset, base_dir=state_dir)
-    syncer = HistorySyncer(syncer_backend, chain_interface, block_callback=cache_filter.block_callback)
+    syncer = HistorySyncer(syncer_backend, chain_interface, block_callback=callback)
     return [syncer]
 
 
 def setup_backend_head(chain_spec, block_offset, block_limit, state_dir, callback, chain_interface, sync_offset=0, skip_history=False):
     syncer_backend = FileBackend.live(chain_spec, block_offset, base_dir=state_dir)
-    syncer = (HeadSyncer(syncer_backend, chain_interface, block_callback=cache_filter.block_callback))
+    syncer = HeadSyncer(syncer_backend, chain_interface, block_callback=callback)
     return [syncer]
 
 
-if __name__ == '__main__':
+def main():
     o = block_latest()
     r = rpc.do(o)
     block_offset = int(strip_0x(r), 16) + 1
@@ -226,10 +229,10 @@ if __name__ == '__main__':
 
     if block_offset == -1:
         block_offset = block_latest
-    elif not config.true('_KEEP_ALIVE'):
-        if block_limit == 0:
-            block_limit = block_latest
-
+#    elif not config.true('_KEEP_ALIVE'):
+#        if block_limit == 0:
+#            block_limit = block_latest
+#
     address_rules = setup_address_rules(
             includes_file=args.includes_file,
             excludes_file=args.excludes_file,
@@ -252,7 +255,6 @@ if __name__ == '__main__':
             ]
 
     if args.filter != None:
-        import importlib
         for fltr in args.filter:
             m = importlib.import_module(fltr)
             fltr_object = m.Filter(rules_filter=address_rules)
@@ -278,7 +280,13 @@ if __name__ == '__main__':
                 skip_history=config.true('_NO_HISTORY'),
                 )
 
-    out_filter = OutFilter(rules_filter=address_rules)
+    renderers = ['local.ge']
+    renderers_mods = []
+    for renderer in renderers:
+        m = importlib.import_module(renderer)
+        renderers_mods.append(m)
+
+    out_filter = OutFilter(chain_spec, rules_filter=address_rules, renderers=renderers_mods)
     filters.append(out_filter)
 
     i = 0
@@ -291,3 +299,7 @@ if __name__ == '__main__':
         sys.stderr.write("sync {} done at block {}\n".format(syncer, r))
 
         i += 1
+
+
+if __name__ == '__main__':
+    main()
diff --git a/test_requirements.txt b/test_requirements.txt